x86: preserve ZF across BT-family instructions - #88
Open
DORA-B wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This completes the ZF-preservation fix started by #79 for
BT,BTS,BTR, andBTC. Intel defines CF as the selected bit and ZF as unaffected for all four instructions.PR #79 changed only the amd64 register-index decoder. Three other decoder paths still replace the flag state with CF alone, and the changed path reads raw
CC_DEP1, which is not packed RFLAGS when the preceding flags are lazy.This is also a follow-up to the remaining BTC portion of angr/angr#6067. That grouped issue is closed because its separate MUL fix used
Fixes #6067; the closure does not cover these remaining VEX paths.Missing cases after #79
0F A3/AB/B3/BB)cmpis mishandled0F BA /4-/7)0F A3/AB/B3/BB)0F BA /4-/7)Each decoder handles both register and memory destinations, and the issue applies to BT/BTS/BTR/BTC because they share the same flag-writing code.
Root cause
VEX represents arithmetic flags lazily. After
cmp, the state is conceptually:PR #79 reads
CC_DEP1directly and treats it as packed RFLAGS before switchingCC_OPto COPY. Operand bit 6 is therefore copied as ZF. The untouched paths instead switch to COPY withCC_DEP1containing only the new CF, which always clears ZF.The fix materializes the previous flags with
mk_amd64g_calculate_rflags_all()ormk_x86g_calculate_eflags_all(), replaces only CF with the selected bit, and stores the result in COPY form.Reproducer
With pyvex built from current VEX master:
Current master:
This branch:
Validation
Built pyvex 9.3.0 with this exact VEX branch and checked the cross-product of:
Current master passes 32/64 and fails every prior-ZF=1 case. This branch passes all 64/64 cases with the destination value, CF, and ZF matching the reference.
Intel reference: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html (Volume 2A, BT/BTC/BTR/BTS
Flags Affected).