// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/// Soundness PoC: `mem_opt.rs` only updates `memory_state[word_offset]` when
/// recording an mstore, where `word_offset = static_offset / 32 * 32`. An
/// *unaligned* `mstore(0x70, v)` writes 32 bytes from byte 0x70 to 0x90, so
/// it overwrites the lower half of the word starting at 0x80. mem_opt only
/// touches `memory_state[0x60]` and leaves `memory_state[0x80]` intact.
///
/// A subsequent `mload(0x80)` finds the still-cached tracked entry at 0x80
/// (offset == 0x80, no aliasing check across overlap with 0x70) and is
/// forwarded to the *pre-overwrite* stored value. EVM reads the actual
/// memory which contains the lower half of the unaligned store plus the
/// untouched upper half of the original.
contract UnalignedMStoreBug {
function bug() external pure returns (bytes32 r) {
assembly {
// 32 byte sentinel at the aligned word 0x80.
mstore(0x80, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
// Unaligned write: 16 bytes of 0xbb at 0x70..0x80 and 16 bytes of
// 0xcc at 0x80..0x90 (overwriting the lower half of the sentinel).
mstore(0x70, 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc)
// mem_opt forwards the stale sentinel, missing the partial overwrite.
r := mload(0x80)
}
}
}