Skip to content

fix(common): make getDetailed span-consistent for WAIT-prefixed x87 instructions#134

Open
r0ny123 wants to merge 2 commits into
danielplohmann:masterfrom
r0ny123:fix/wait-prefix-x87-detail
Open

fix(common): make getDetailed span-consistent for WAIT-prefixed x87 instructions#134
r0ny123 wants to merge 2 commits into
danielplohmann:masterfrom
r0ny123:fix/wait-prefix-x87-detail

Conversation

@r0ny123

@r0ny123 r0ny123 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What & why

Addresses #114. SmdaInstruction.getDetailed() re-disassembles the stored instruction bytes with Capstone, which can split a single SMDA/IDA instruction into two. The classic case is a WAIT-prefixed x87 op:

9bd93c24  ->  wait                       (1 byte)
              fnstcw word ptr [esp]       (3 bytes)

The old code took with_details[-1] and logged a warning every time. That happened to return the right detail here, but only by luck, and it would mis-select for any non-trailing split.

Fix

  • Drop standalone wait/fwait prefix instructions, then return the trailing operation instruction. Its operands and its address + size line up with the end of the stored byte span (0x4d3f1f1 + 3 == 0x4d3f1f0 + 4), so the returned detail is span-consistent.
  • The known WAIT-prefix pattern is now silent; a warning is emitted only for genuinely unexpected splits (0 or >1 non-prefix instructions), and it now names the mnemonics involved.
  • Replaced the bare assert len(...) == 1 (strippable under python -O) with an explicit ValueError for the zero-instruction case.
  • Removed the stale TODO comment block.

Tests

New tests/testSmdaInstructionDetail.py:

  • ordinary single instruction returned unchanged
  • 9bd93c24 regression: returns fnstcw, carries the memory operand, address + size reaches the span end, and emits no warning
  • empty bytes raise ValueError
  • non-Intel architecture raises NotImplementedError

make test green locally (incl. testIntegration, which exercises getDetailed() via data-ref recovery); ruff clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved instruction decoding to correctly handle x87 floating-point wait instructions that may be decoded as separate operations
    • Enhanced error handling for cases where instruction bytes cannot be decoded
  • Tests

    • Added test coverage for instruction detail extraction and related edge cases

r0ny123 and others added 2 commits June 10, 2026 17:05
…nstructions

SmdaInstruction.getDetailed() blindly returned the last Capstone instruction when
the stored bytes decoded to more than one. For WAIT-prefixed x87 forms (e.g.
`9bd93c24` -> `wait` + `fnstcw word ptr [esp]`, recorded as one instruction by
SMDA/IDA) this happened to land on the right detail but did so by accident and
warned on every occurrence.

Select the detail deliberately: drop standalone WAIT/FWAIT prefix instructions and
return the trailing x87 operation, whose operands and (address + size) match the
stored byte span. The known prefix pattern is now silent; only genuinely unexpected
splits warn. Replace the strip-able `assert` with an explicit ValueError for the
zero-instruction case.

Closes danielplohmann#114

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial self-review caught a cross-file regression from changing getDetailed()
to raise ValueError on undecodable bytes (replacing the old strip-able assert):
escapeBinaryPtrRef() only caught (AttributeError, AssertionError, NotImplementedError)
to gracefully default its pack_format, so the new ValueError would propagate and crash
escaping for an instruction with a [disp] operand whose stored bytes cannot be decoded.

Add ValueError to that except tuple and a regression test. NON_OPERATIONAL_EXCEPTION_TYPES
is intentionally left unchanged: an undecodable byte span is an operational data issue,
not a programming error, so treating it as swallowable during analysis is correct.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant