fix: size dict elements buffer to HashMap capacity, not len#1646
Merged
Conversation
3d83051 to
a2d2a66
Compare
When materializing a Felt252Dict value, the elements buffer was arena-allocated with room for `map.len()` slots. The runtime's `dict_get` only grows the buffer once the backing HashMap is full, so a runtime insert of a new key could write one slot past the end of the buffer and corrupt the arena. Allocate the buffer using the HashMap's capacity (read after `reserve`, which usually over-allocates) so there is always room for the runtime to fill every slot the HashMap can hold. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
a2d2a66 to
14d5c5e
Compare
orizi
approved these changes
Jun 18, 2026
orizi
left a comment
Collaborator
There was a problem hiding this comment.
@orizi reviewed 1 file and all commit messages, and made 1 comment.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on TomerStarkware).
Benchmarking resultsBenchmark for program
|
| Command | Mean [s] | Min [s] | Max [s] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
10.432 ± 0.045 | 10.368 | 10.496 | 5.74 ± 0.04 |
cairo-native (embedded AOT) |
1.818 ± 0.011 | 1.806 | 1.838 | 1.00 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
1.828 ± 0.015 | 1.801 | 1.848 | 1.01 ± 0.01 |
Benchmark for program dict_snapshot
Open benchmarks
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
517.0 ± 3.8 | 510.3 | 523.8 | 1.00 |
cairo-native (embedded AOT) |
1629.6 ± 12.2 | 1614.2 | 1654.5 | 3.15 ± 0.03 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
1666.1 ± 12.0 | 1649.7 | 1689.0 | 3.22 ± 0.03 |
Benchmark for program factorial_2M
Open benchmarks
| Command | Mean [s] | Min [s] | Max [s] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
4.639 ± 0.014 | 4.620 | 4.662 | 2.21 ± 0.01 |
cairo-native (embedded AOT) |
2.097 ± 0.007 | 2.089 | 2.109 | 1.00 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
2.108 ± 0.012 | 2.082 | 2.127 | 1.01 ± 0.01 |
Benchmark for program fib_2M
Open benchmarks
| Command | Mean [s] | Min [s] | Max [s] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
4.560 ± 0.043 | 4.524 | 4.670 | 2.79 ± 0.03 |
cairo-native (embedded AOT) |
1.635 ± 0.012 | 1.614 | 1.652 | 1.00 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
1.669 ± 0.007 | 1.658 | 1.682 | 1.02 ± 0.01 |
Benchmark for program linear_search
Open benchmarks
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
560.8 ± 4.0 | 555.4 | 565.0 | 1.00 |
cairo-native (embedded AOT) |
1649.8 ± 9.3 | 1636.1 | 1663.7 | 2.94 ± 0.03 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
1692.6 ± 6.6 | 1684.8 | 1708.9 | 3.02 ± 0.02 |
Benchmark for program logistic_map
Open benchmarks
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
Cairo-vm (Rust, Cairo 1) |
474.9 ± 3.7 | 470.7 | 482.0 | 1.00 |
cairo-native (embedded AOT) |
1801.4 ± 10.7 | 1785.6 | 1815.3 | 3.79 ± 0.04 |
cairo-native (embedded JIT using LLVM's ORC Engine) |
1911.0 ± 13.5 | 1895.2 | 1938.2 | 4.02 ± 0.04 |
Benchmark results Main vs HEAD.Base
Head
Base
Head
Base
Head
Base
Head
Base
Head
Base
Head
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When materializing a
Felt252Dictvalue (Value::Felt252Dict→ native), the elements buffer was arena-allocated with room formap.len()slots. The runtime'sdict_getonly grows the elements buffer once the backingHashMapis full, so a runtime insert of a new key could write one slot past the end of the buffer and corrupt the arena.This reorders the allocation so the
FeltDictstruct is created andreserved first, then sizes the elements buffer to the HashMap's actualcapacity()(whichreserveusually over-allocates). That guarantees there is always room for the runtime to fill every slot the HashMap can hold.Changes
src/values.rs: allocate/register theFeltDictbefore the elements buffer, and size the buffer todict.mappings.capacity()instead ofmap.len().🤖 Generated with Claude Code
This change is