fix: widen memory cost square to 64-bit in grow_memory - #1
Open
hatemosphere wants to merge 1 commit into
Open
Conversation
grow_memory computed new_words * new_words in uint32; at 65536 words (2 MiB) the square is exactly 2^32 and wraps, turning the expansion cost delta into ~4.3e9 gas and OOG-ing any frame that grows memory past 2 MiB. 65535 words still fits, so smaller memory is unaffected. Found via zilkworm preflight kWrongBlockGas on mainnet blocks 25723470, 25728210, 25737170 (>2 MiB abi-encode buffers); all three validate byte-exact against canonical gas with the fix.
somnergy
approved these changes
Aug 20, 2026
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.
grow_memory computes new_words * new_words in uint32. At exactly 65536 memory words (2 MiB) the square is 2^32 and wraps, so the expansion cost delta underflows to ~4.3e9 gas and any frame growing memory past 2 MiB OOGs instantly. 65535 words still fits in 32 bits, so everything below 2 MiB is unaffected.
Hit on mainnet by zilkworm preflight (kWrongBlockGas) on blocks 25723470, 25728210 and 25737170 - Resupply liquidation txs that abi-encode >2 MiB call buffers in a loop. With this fix all three validate byte-exact against canonical gas, and 20 recent healthy blocks pass as regression.
The widened square is still a single mul/mulhu pair on rv32im.
Note: includes a regression test crossing the 2 MiB boundary, written to upstream evmone conventions. This branch's unittest suite does not currently build standalone (test/state drift vs lib, e.g. TransactionReceipt::logs_bloom_filter), so the test is syntax-checked against branch headers only.