diff options
author | iximeow <me@iximeow.net> | 2021-08-21 13:13:26 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2021-08-21 13:15:46 -0700 |
commit | 9687a5af1d712da41992cba8d241ddef8bdc50ec (patch) | |
tree | a17d37ad3096c86f7c0247ed08ef2ff5a9f27cf2 /src | |
parent | cef4feeaf9c64e03a6728f267750ac2fb32eb9ff (diff) |
clarify inaccurate 32/16-bit `call/jmp [mem]` mem_size
Diffstat (limited to 'src')
-rw-r--r-- | src/protected_mode/mod.rs | 14 | ||||
-rw-r--r-- | src/real_mode/mod.rs | 18 |
2 files changed, 22 insertions, 10 deletions
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 8381d68..79eb1b1 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -4223,6 +4223,15 @@ impl Instruction { /// the corresponding `MemoryAccessSize` may report that the size of accessed memory is /// indeterminate; this is the case for `xsave/xrestor`-style instructions whose operation size /// varies based on physical processor. + /// + /// ## NOTE + /// + /// the reported size is correct for displayed operand sizes (`word [ptr]` will have a + /// `MemoryAccessSize` indicating two bytes) but is _not_ sufficient to describe all accesses + /// of all instructions. the most notable exception is for operand-size-prefixed `call`, where + /// `66ff10` is the instruction `call word [eax]`, but will push a four-byte `eip`. this same + /// imprecision exists for `jmp word [mem]` as well. tools must account for these inconsistent + /// sizes internally. pub fn mem_size(&self) -> Option<MemoryAccessSize> { if self.mem_size != 0 { Some(MemoryAccessSize { size: self.mem_size }) @@ -7516,9 +7525,8 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe return Err(DecodeError::InvalidOperand); } } else { - if opcode == Opcode::CALL || opcode == Opcode::JMP { - instruction.mem_size = 4; - } else if opcode == Opcode::PUSH || opcode == Opcode::POP { + if opcode == Opcode::CALL || opcode == Opcode::JMP || + opcode == Opcode::PUSH || opcode == Opcode::POP { if instruction.prefixes.operand_size() { instruction.mem_size = 2; } else { diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 548c42e..8a7e453 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -4223,6 +4223,15 @@ impl Instruction { /// the corresponding `MemoryAccessSize` may report that the size of accessed memory is /// indeterminate; this is the case for `xsave/xrestor`-style instructions whose operation size /// varies based on physical processor. + /// + /// ## NOTE + /// + /// the reported size is correct for displayed operand sizes (`word [ptr]` will have a + /// `MemoryAccessSize` indicating two bytes) but is _not_ sufficient to describe all accesses + /// of all instructions. the most notable exception is for operand-size-prefixed `call`, where + /// `66ff10` is the instruction `call dword [eax]`, but will push a four-byte `eip`. this same + /// imprecision exists for `jmp dword [mem]` as well. tools must account for these inconsistent + /// sizes internally. pub fn mem_size(&self) -> Option<MemoryAccessSize> { if self.mem_size != 0 { Some(MemoryAccessSize { size: self.mem_size }) @@ -7516,13 +7525,8 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe return Err(DecodeError::InvalidOperand); } } else { - if opcode == Opcode::CALL || opcode == Opcode::JMP { - if instruction.prefixes.operand_size() { - instruction.mem_size = 4; - } else { - instruction.mem_size = 2; - } - } else if opcode == Opcode::PUSH || opcode == Opcode::POP { + if opcode == Opcode::CALL || opcode == Opcode::JMP || + opcode == Opcode::PUSH || opcode == Opcode::POP { if instruction.prefixes.operand_size() { instruction.mem_size = 4; } else { |