THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Summary
Lifting seven bytes of s390x code segfaults the interpreter. There is no Python
exception — the process dies with SIGSEGV inside libVEX:
Fatal Python error: Segmentation fault
Current thread (most recent call first):
File "pyvex/lifting/libvex.py", line 87 in _lift
File "pyvex/lifting/lifter.py", line 110 in lift
File "pyvex/lifting/lift_function.py", line 134 in lift
lift_function.py already pads byte input with eight zero bytes specifically to
give libVEX room to over-read, so the intent to tolerate a truncated final
instruction is there. The s390x front end reads past even that padding when the
block ends mid-instruction: the input below is a complete a75b ffff followed by
c6 50 ff, the first three bytes of a six-byte RIL-format instruction.
Because it is a segfault rather than an exception, a caller cannot defend against
it — the whole process is lost, which matters for anything lifting untrusted or
partially-mapped code.
Reproduction
Deterministic, and independent of the load address:
import pyvex
import archinfo
pyvex.lift(bytes.fromhex("a75bffffc650ff"), 0x1000, archinfo.arch_from_id("s390x"))
$ python repro.py; echo "exit=$?"
Fatal Python error: Segmentation fault
exit=139
Tested with pyvex 26f2b61c618bdd4e01be44562c97b824be399200 and archinfo
dad25b035d090c9165e85a65f16322456568df43. Reached in practice through
CFGFast, which lifts at addresses it discovers by scanning and so routinely
hands the lifter a block that ends mid-instruction.
Scope
Found by a corpus sweep running CFGFast over every unit that loads. Native
crashes account for 81 VEX-lifted units at 30% of that sweep, all real-world
material and concentrated in stock Debian port binaries; s390x is the largest
group among them.
The audit records these as a worker killed by a signal, with no Python
traceback, so the true total may be larger — a native crash cannot be attributed
to a call site from inside the dead process.
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Summary
Lifting seven bytes of s390x code segfaults the interpreter. There is no Python
exception — the process dies with SIGSEGV inside libVEX:
lift_function.pyalready pads byte input with eight zero bytes specifically togive libVEX room to over-read, so the intent to tolerate a truncated final
instruction is there. The s390x front end reads past even that padding when the
block ends mid-instruction: the input below is a complete
a75b fffffollowed byc6 50 ff, the first three bytes of a six-byte RIL-format instruction.Because it is a segfault rather than an exception, a caller cannot defend against
it — the whole process is lost, which matters for anything lifting untrusted or
partially-mapped code.
Reproduction
Deterministic, and independent of the load address:
Tested with pyvex
26f2b61c618bdd4e01be44562c97b824be399200and archinfodad25b035d090c9165e85a65f16322456568df43. Reached in practice throughCFGFast, which lifts at addresses it discovers by scanning and so routinelyhands the lifter a block that ends mid-instruction.
Scope
Found by a corpus sweep running
CFGFastover every unit that loads. Nativecrashes account for 81 VEX-lifted units at 30% of that sweep, all real-world
material and concentrated in stock Debian port binaries; s390x is the largest
group among them.
The audit records these as a worker killed by a signal, with no Python
traceback, so the true total may be larger — a native crash cannot be attributed
to a call site from inside the dead process.