SimLinux.state_blank pre-grows the stack by a fixed 0x20 pages without
checking that 0x20 pages exist beneath the stack pointer. When they do
not, the allocation loop wraps past address 0 and hands out the remainder
at the top of the address space.
On x86-64 that is silent: blank_state(stack_end=0x10000) maps sixteen
stack pages from 0x0 up and sixteen more from 0xfffffffffffff000 down.
Where the wrap reaches a page the same call already handed out, the state
fails with SimSegfaultException("stack collided with heap") instead, and
where it reaches the loaded image it replaces it with blank pages.
Skip the pre-grow when that much space does not exist. Clamping it to the
space that does exist is not an option: the pre-allocated pages are not
backed by the loader, so a stack that reaches down to an image beneath it
hides that image. The pages that are skipped are still faulted in on
demand.
Also reject an allocation that does not fit beneath the top of the stack
in allocate_stack_pages() itself, so a caller that asks for one gets an
error rather than pages at the top of the address space.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* Rebuild phi statements instead of mutating them in place
* Update the phis of every dispatcher target
* Return only the variables the outlined region defines
* Clinic: Skip the second pre-SSA-level1 _simplify_function when it cannot help.
* Clinic: Merge the two identical post-SSA-level1 _simplify_function calls.
* AILSimplifier, SLiveness: Skip recomputation that cannot change anything.
* SimStruct: Remove _arch_memo to fix the cache leak.
* Fix the comment
* Better typing.
* Fix RustSimTypes.
* More fixes.
* Fix caching for anonymous structs.
* SimUnion: Cache alignment.
* Convert returnty to a arch-ed returnty.
* RustSimType: Do not shadow SimType.with_arch.
* Rust: Bind an arch to types before they reach the type solver.
* RustSimType: Make it a subclass of SimType.
* Decompiler: Test common C conditions.
* Improve c-style null compatison implementation
* Make order-sensitive
---------
Co-authored-by: Kevin Phoenix <kevin@kphoenix.us>
* Fix signed division and remainder in the pcode engine
OpBehaviorIntSdiv and OpBehaviorIntSrem used Claripy's `/` and `%`, which are
unsigned bit-vector operations. For negative operands they therefore produced
the same results as the unsigned INT_DIV and INT_REM behaviors.
INT_SDIV now uses claripy.SDiv (truncation toward zero). INT_SREM is defined as
in1 - SDiv(in1, in2) * in2, giving a remainder with the dividend's sign, which
matches the p-code semantics documented in the class comments.
For 64-bit -5 and 2, INT_SDIV now yields -2 (0xfffffffffffffffe) and INT_SREM
yields -1 (0xffffffffffffffff) instead of large unsigned values.
The arithmetic behavior test table enables both INT_SDIV and INT_SREM with the
matching signed reference expressions, and a new concrete test checks mixed-sign
combinations (-5/2, 5/-2, -5/-2, ...) that an unsigned implementation cannot
satisfy.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Use claripy.SMod for INT_SREM
Per review, INT_SREM uses claripy.SMod directly instead of the equivalent
in1 - claripy.SDiv(in1, in2) * in2. Verified identical to a truncated-toward-zero
reference over 100k random 64-bit pairs, including the INT_MIN / -1 corner.
* Address pcode signed arithmetic review comments
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* AIL: Merge likes/matches into a single mode-parameterized walk
* AIL: Make __eq__ idx-aware at every node, not just the root
* AIL: Stop hashing fields that equality does not compare
* AIL: Regression-test the hash/eq contract
* AIL: Compare bits in StringLiteral and Struct
* AIL: Replace the CMP_* constants with a CmpMode enum
* AIL: cargo fmt
* AIL: Compare and hash rounding_mode on Convert and BinaryOp
* Update comments.