Fix wrapped pointer arithmetic and comparisons - #836
Conversation
Why this PR no longer changes memory regionsWhile auditing pointer-to-integer conversions, I found a separate, pre-existing memory-splitting soundness issue. It is not caused by wrapped-pointer arithmetic and The problematic shape is: %p = malloc(...)
%i = ptrtoint ptr %p to i64
%q = inttoptr i64 %i to ptr
store 0, ptr %q
store 1, ptr %p
%v = load ptr %q
assert(%v == 0) ; must failWith The cast canonicalization in this PR only ensures that equal machine pointer values have the same numerical Boogie My initial attempted fix changed A proper follow-up should distinguish at least:
That work needs dedicated regressions for false proofs, external pointers, map counts, and performance. PR 836 therefore stays confined to wrapped pointer value semantics, and |
Fixes #804.
This also covers the GEP false alarm originally reported in #682.
Problem
Wrapped integers are represented as unbounded Boogie integers and normalized when their machine-width value is observed. Pointer operations did not consistently follow that rule:
$add.ref,$sub.ref, and$mul.refreturned unbounded arithmetic results, so a constrained 64-bit index could address a different memory cell through a noncanonical representative.Approach
$tos.$tou.Keeping signed predicates linear is intentional. SMACK's allocation models use them to bound pointer values. Wrapping every pointer predicate, as attempted in the old
fixed-pa-wrappedbranch, admits noncanonical allocator values and made Corral'sno-reusecontracts time out.For integral pointers with the module's default pointer width, the conversion formulas follow LLVM's required truncation and zero-extension rules. Choosing
$tosas the representative preserves values modulo2^N; pointer-to-integer-to-pointer round trips preserve canonical pointer values. Alternate-width and non-integral address spaces remain outside SMACK's existing single-pointer-width model and are not addressed here.This change is confined to pointer translation. It does not modify SeaDsa region construction or SMACK's memory-splitting policy.
Tests
--integer-encoding=wrapped-integer#804 C regression with an unsigned 64-bit GEP index.INT64_MAXtoINT64_MIN, distinct signed/unsigned pointer ordering, and pointer/integer roundtrip equality.c/basicexhaustive matrix: 510/510 passed.c/dataexhaustive matrix: 498/498 passed.