bugc: give each memory-homed scalar its own word, stop byte-packing#272
Merged
Conversation
The frame/static memory allocator byte-packed several sub-word scalars (address, bool, intN/uintN, bytesN) into one 32-byte word. But a memory-homed value is read and written with full-word MLOAD/MSTORE, so two sub-word scalars sharing a word clobber each other: storing one writes the whole word and overwrites the other's bytes. This is a real runtime corruption — e.g. an address packed with a bool reads back zero once the bool is stored, because the bool's full-word store overwrites the address's low bytes. Allocate one full 32-byte word per memory-homed value instead. A word is the EVM's natural load/store granularity and memory is not scarce at O0, so the only cost is a slightly larger frame. Each scalar now solely occupies its word, so its full-word store cannot touch a neighbor. Adds a memory-planning test asserting that several sub-word scalars each receive a distinct, word-aligned slot (it fails against the old packing, where all four collapsed into one word).
Contributor
|
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.
The frame/static memory allocator byte-packed several sub-word scalars (
address,bool,intN/uintN,bytesN) into one 32-byte word. But a memory-homed value is read and written with full-wordMLOAD/MSTORE, so two sub-word scalars sharing a word clobber each other: storing one writes the whole word and overwrites the other's bytes.This is a real runtime corruption, not just a debug-info artifact. Confirmed with an execution trace: for
f(ad: address, flag: bool, …)whereadandflagbyte-pack into one word, at a live-frame stepadreads back0x000…000instead of its argument0xaA— the bool's full-wordMSTOREoverwrote the address's low bytes. A program that read the address after the bool store would observe zero.Fix
Allocate one full 32-byte word per memory-homed value instead of byte-packing sub-word scalars. A word is the EVM's natural load/store granularity and memory is not scarce at
O0, so the only cost is a slightly larger frame. Each scalar now solely occupies its word, so its full-word store cannot touch a neighbor.Test
Adds a memory-planning test asserting that several sub-word scalars (
address,bool,uint8,bytes4) each receive a distinct, word-aligned slot. It fails against the old packing (all four collapse into one word) and passes with the fix.