Skip to content

Update ascending counter, lower bound, and fmp propagation after fuzzy dedup - #617

Open
elle-j wants to merge 2 commits into
cl/ny-heap-opt-loop-carried-offsetsfrom
lj/loop-counter-ascending
Open

elle-j wants to merge 2 commits into
cl/ny-heap-opt-loop-carried-offsetsfrom
lj/loop-counter-ascending

Conversation

@elle-j

@elle-j elle-j commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Some fixes for addressing this PR comment and this PR comment.

`loop_counter_ascends` accepted `post` yielding the counter plus any
addend, so `add(p, not(31))` (solc's optimized `sub(pointer, 0x20)`)
kept its seed as a lower bound. A counter that did not ascend got the
lower bound 0, so `add(0x80, counter)` got the lower bound `0x80`,
although a counter counting down from 0 wraps to 2^256 − 0x20 and the
sum then wraps to `0x60` and `0x40`. `shl`, `sub` and all other
operations gave no lower bound, so a store or copy length through them
never marked the free memory pointer unbounded. A pointer advanced in
the loop body, as in solc's storage array copy loop, counted as not
ascending and cost the range proof.

A counter now only ascends when the body's yield, every `continue` and
`post` hand it on unchanged or plus a static step, and otherwise has no
lower bound. `OffsetInfo::iteration_range` replaces `lower_bound`. It
keeps a lower bound through `add`, `mul` and `shl` by a static shift
only while the result fits 256 bits, and gives every other operation on
literals and loop counters none, so a store or copy through such a value
sets `fmp_could_be_unbounded`, also for a destination that
`is_free_pointer_relative` accepts. Post inputs and loop outputs get
ranges too, nested loops' `break`and `continue` no longer count for the
outer loop, and the `Shl` arm is corrected to read the shift from `lhs`.
Fuzzy dedup turns the literal offsets of `Scratch` stores into a
parameter and keeps the tag, but `Scratch` only says the store starts
below `0x40`. A word stored at `0x3f` still covers `[0x40, 0x5e]`. The
heap analysis ignored the tag, so after the merged helper overwrote the
pointer word, the range proof truncated the pointer read. A full-word
`MStore` with a non-static offset tagged `Scratch` now sets
`fmp_could_be_unbounded`.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant