3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-20 15:40:37 +00:00
z3/src
Can Cebeci e4e5d57cf6 Fix stale func_interp entry table after compression (#9906)
## Summary
Fix a use-after-free in `func_interp::compress()`.

When a function interpretation had previously grown large enough to
allocate `m_entry_table`, `compress()` could deallocate entries whose
result matched the else-case but leave the hash table intact. Later
`get_entry()` lookups could then return freed `func_entry*` values,
which showed up during model checking as a corrupted expression result
from `model_evaluator`.

## Root cause
`func_interp::compress()` compacted `m_entries` and freed removed
entries, but it did not rebuild or clear `m_entry_table`.

This left stale pointers in the lookup table whenever:
- the table had already been allocated on a larger interpretation, and
- compression removed some entries.

In the reported case, model evaluation rewrote `stack_s!1041` through
`BR_REWRITE1`, fetched a freed `func_entry` result from the stale table,
and then tripped an assertion in `expr::get_sort()` during quantifier
model checking.

## Fix
After compression removes entries, rebuild `m_entry_table` from the
surviving `m_entries`, or clear it when the surviving interpretation is
small.

## Regression coverage
Added a unit regression in `src/test/model_evaluator.cpp` that:
- creates a `func_interp` large enough to allocate `m_entry_table`,
- compresses away almost all entries,
- checks that removed keys no longer resolve, and
- checks that the surviving key still resolves to the correct result.

## Validation
- `../build/z3 ebso-115.smt2` previously hit an assertion in
`rewriter_def.h` / `ast.cpp`; after the fix it no longer asserts.
- `./test-z3 model_evaluator` passes with the new regression.

## Reproducer
I did not produce a smaller SMT2 benchmark in this change. The original
reproducer I used was `ebso-115.smt2`, and the new unit regression
directly exercises the stale-entry-table path in-process.

Co-authored-by: Can Cebeci <t-cancebeci@microsoft.com>
2026-06-19 17:36:23 -07:00
..
ackermannization Fix off-by-one vulnerabilities: use range-based for on goals; cache loop bound 2026-02-19 22:37:22 +00:00
api python: build a PyPI-publishable Pyodide (PEP 783) wheel (#9891) 2026-06-19 17:36:19 -07:00
ast Update seq_rewriter.cpp 2026-06-19 17:36:18 -07:00
cmd_context Use "override" keyword where needed. (#9892) 2026-06-19 17:36:19 -07:00
math Use "override" keyword where needed. (#9892) 2026-06-19 17:36:19 -07:00
model Fix stale func_interp entry table after compression (#9906) 2026-06-19 17:36:23 -07:00
muz Add rlimit support in fixedpoint parameters (#9798) 2026-06-10 15:13:05 -07:00
nlsat making try-for tactic exception resilient on cancelation 2026-04-26 15:58:24 -07:00
opt Fixes necessary to compile z3 included in clang-tidy via FetchContents. (#9768) 2026-06-08 19:44:01 -07:00
params prepare for lambda unfolding in ho-matcher and selectively enable ho matching 2026-05-22 13:25:01 -07:00
parsers Fix off-by-one column after comment lines in SMT2 scanner (#9808) 2026-06-10 06:49:31 -07:00
qe Cleanup thanks to Copilot (#9709) 2026-06-04 10:46:33 -07:00
sat refactor solver to include settable stats 2026-06-07 14:17:38 -07:00
shell Fixes necessary to compile z3 included in clang-tidy via FetchContents. (#9768) 2026-06-08 19:44:01 -07:00
smt extend cases for process_formulas_on_stack 2026-06-19 17:36:20 -07:00
solver Use "override" keyword where needed. (#9892) 2026-06-19 17:36:19 -07:00
tactic Fix reference to recfun::util in lia2card_tactic.cpp 2026-06-19 17:36:18 -07:00
test Fix stale func_interp entry table after compression (#9906) 2026-06-19 17:36:23 -07:00
util Fix GMP bit-vector modulo semantics causing signed BV unsoundness and invalid SMT2 numerals (#9899) 2026-06-19 17:36:23 -07:00
CMakeLists.txt git bindings v1.0 2026-02-18 21:02:25 -08:00