aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/mod.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-11-19 18:13:24 -0800
committeriximeow <me@iximeow.net>2020-11-19 18:13:24 -0800
commit81e9b93aab9217cf7cb508f64b19fc1c0df024b5 (patch)
tree4a17eed4bd3191d3f02417d6c7d63420a474fb95 /src/long_mode/mod.rs
parente3a400b7a96284d1394cd710ea3bcee01dbfe95f (diff)
fix decoding of rex-prefixed modrm+sib operands selecting index 0b100 and base 0b1010.1.4
for memory operands with a base, index, and displacement either the wrong base would be selected (register number ignored, so only `*ax` or `r8*` would be reported), or yaxpeax-x86 would report a base register is present when it is not (`RegIndexBaseScaleDisp` when the operand is actually `RegScaleDisp`) thank you to Evan Johnson for catching and reporting this bug! also bump crate version to 0.1.4 as this will be immediately tagged and released.
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r--src/long_mode/mod.rs16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 363c605..d165e38 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -5665,20 +5665,28 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m
OperandSpec::DispU32
} else {
+ instr.modrm_mmm.num |= 0b101;
+
if instr.prefixes.rex().x() {
instr.sib_index.num = 0b1100;
let scale = 1u8 << (sibbyte >> 6);
instr.scale = scale;
if disp == 0 {
- OperandSpec::RegIndexBaseScale
+ if modbits == 0 {
+ OperandSpec::RegScale
+ } else {
+ OperandSpec::RegIndexBaseScale
+ }
} else {
instr.disp = disp as i64 as u64;
- OperandSpec::RegIndexBaseScaleDisp
+ if modbits == 0 {
+ OperandSpec::RegScaleDisp
+ } else {
+ OperandSpec::RegIndexBaseScaleDisp
+ }
}
} else {
- instr.modrm_mmm.num |= 0b101;
-
if disp == 0 {
OperandSpec::Deref
} else {