Fix NULL-pointer dereference in sym_movcond_internal (#56)#76
Open
Emad-Mahmodi wants to merge 2 commits into
Open
Fix NULL-pointer dereference in sym_movcond_internal (#56)#76Emad-Mahmodi wants to merge 2 commits into
Emad-Mahmodi wants to merge 2 commits into
Conversation
A movcond with concrete comparison operands (c1_expr and c2_expr both NULL) but a symbolic selected value (v1_expr or v2_expr non-NULL) does not hit the all-NULL early return. The concrete-operand fixup then took the bit width from a sibling operand via _sym_bits_helper(c2_expr), which is itself NULL in that case, so Expr::bits() dereferenced a NULL 'this' (SIGSEGV, fault address 0x14). Use the result_bits argument the helper already provides instead, which is also consistent with the assertions that immediately follow.
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
Fixes #56. SymQEMU crashes with
QEMU internal SIGSEGV {code=MAPERR, addr=0x14}after generating a few test cases. The root cause is a NULL-pointer dereference
in
sym_movcond_internal(accel/tcg/tcg-runtime-sym.c).Backtrace
The fault is a read at
0x14withthis == NULL(offset ofExpr::bits_):signal SIGSEGV: address not mapped to object (fault address=0x14)
#0 qsym::Expr::bits() const expr.h:129 // return bits_; (offset 0x14)
#1 ::_sym_bits_helper(SymExpr)
#2 sym_movcond_internal tcg-runtime-sym.c
#3 helper_sym_movcond_i64
#4 code_gen_buffer
#5 cpu_tb_exec cpu-exec.c
Root cause
The early return only fires when all four operand expressions are NULL:
A movcond whose comparison operands are both concrete (
c1_exprandc2_exprare NULL) but whose selected value is symbolic (
v1_exprorv2_exprnon-NULL) does not return early. It then reaches:
Here
c2_expris also NULL, so_sym_bits_helper(NULL)callsExpr::bits()on a NULL
this, readingbits_at offset0x14→ SIGSEGV.Concrete example
A movcond of the form
result = concrete_cond ? symbolic_value : 0gives:c1_expr == NULLis true, so_sym_bits_helper(c2_expr)runs withc2_expr == NULLand crashes.This explains why it reproduces with some toolchains but not others (LLVM 15 vs
17, as noted in the issue): whether the guest binary contains such a movcond
depends on how the compiler lowered the code. The bug is latent in all cases
and triggers only when that pattern is emitted.
Fix
The bit width does not need to be borrowed from a sibling operand — the function
already receives it as
result_bits, and the assertions immediately belowconfirm all four operands must equal
result_bits.Regression test
Added
tests/symqemu/binaries/movcond_issue56/(a binary reproducing theissue's program) and
test_movcond_issue56intests/symqemu/test.py. Sincethe harness runs SymQEMU with
check=True, the crash fails the test on theunpatched build and passes once fixed; the reproducer now runs to completion
instead of crashing after ~14 test cases.