Skip to content

target/i386: Call gen_update_cc_op() after set_cc_op() in gen_compute_eflags() - #2373

Open
unknown-1-0 wants to merge 1 commit into
unicorn-engine:devfrom
unknown-1-0:i386-fix-incorrect-flags-on-fault-after-eflags-overwrite
Open

target/i386: Call gen_update_cc_op() after set_cc_op() in gen_compute_eflags()#2373
unknown-1-0 wants to merge 1 commit into
unicorn-engine:devfrom
unknown-1-0:i386-fix-incorrect-flags-on-fault-after-eflags-overwrite

Conversation

@unknown-1-0

Copy link
Copy Markdown

gen_update_cc_op() updates the env->cc_op value only if s->cc_op_dirty is set.
In gen_compute_eflags(), set_cc_op() is responsible for setting that variable to true when needed.

Since gen_update_cc_op() was previously called before set_cc_op() inside gen_compute_eflags(), s->cc_op_dirty might not be set to true when it should be. This can lead to the env->cc_op write being completely omitted in the generated TCG micro-ops.

Although this omission may later be corrected by a gen_update_cc_op() call at the end of disas_insn(), that correction may not happen when the instruction faults before it completes. This can lead to a state where env->cc_src contains the calculated RFLAGS and env->cc_op holds the value other than CC_OP_EFLAGS. This in turn causes incorrect RFLAGS values to be computed after the instruction fault.

Fix this bug by calling gen_update_cc_op() after set_cc_op() to ensure that s->cc_op_dirty is properly updated.

…mpute_eflags()`

`gen_update_cc_op()` updates the `env->cc_op` value only if `s->cc_op_dirty`
is set.
In `gen_compute_eflags()`, `set_cc_op()` is responsible for setting
that variable to `true` when needed.

Since `gen_update_cc_op()` was previously called before `set_cc_op()` inside
`gen_compute_eflags()`, `s->cc_op_dirty` might not be set to `true` when it
should be. This can lead to the `env->cc_op` write being completely omitted
in the generated TCG micro-ops.

Although this omission may later be corrected by a `gen_update_cc_op()` call
at the end of `disas_insn()`, that correction may not happen when
the instruction faults before it completes. This can lead to a state where
`env->cc_src` contains the calculated RFLAGS and `env->cc_op` holds
the value other than `CC_OP_EFLAGS`. This in turn causes incorrect RFLAGS
values to be computed after the instruction fault.

Fix this bug by calling `gen_update_cc_op()` after `set_cc_op()` to ensure
that `s->cc_op_dirty` is properly updated.

Signed-off-by: Andrey Polivoda <apolivodaa433@gmail.com>
@unknown-1-0
unknown-1-0 force-pushed the i386-fix-incorrect-flags-on-fault-after-eflags-overwrite branch from 8bf08a5 to 2378011 Compare July 24, 2026 09:28
@unknown-1-0

Copy link
Copy Markdown
Author

Fixed brace style of the if statement in test_x86_rflags_after_exec()

@unknown-1-0

unknown-1-0 commented Jul 24, 2026

Copy link
Copy Markdown
Author

@wtdcode, I know you are busy reviewing other PRs, but could you please share your opinion on this one before the next release (#2356)?

If you have time, please also take a look at my other x86-related fixes:
#2370 - forces LAHF/SAHF to use AH when REX prefix is used
#2362 - prevents 0xfe/0xff instructions from generating a memory load micro-op when ModRM.reg == 7 (you already commented on that one, I added the tests as you requested)
#2361 - prevents 0xc6/0xc7 instructions from being decoded as MOV when ModRM.reg != 0, + prevents an invalid opcode (#UD) exception when REX.R is set

Thanks!

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