// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
/// Soundness PoC: `mem_opt::optimize_statements` `*Copy` handler
/// (CodeCopy / ExtCodeCopy / ReturnDataCopy / DataCopy /
/// CallDataCopy) only invalidates `memory_state[word(dest)]` when
/// `dest` is statically known. It ignores the *length* entirely, so
/// additional words inside `[dest, dest + length)` keep their stale
/// tracked entries. A subsequent `mload` at the exact tracked offset
/// is forwarded to the pre-overwrite value while EVM reads the
/// actually-overwritten bytes from the copy.
///
/// The dynamic `length` parameter defeats solc's dead-store
/// elimination of the sentinel — solc can't prove that
/// `calldatacopy(0xc0, 0, length)` overwrites bytes `0xe0..0x100`
/// without knowing `length >= 0x40`.
contract CopyOverlapBug {
function bug(uint256 length) external pure returns (bytes32 r) {
assembly {
mstore(0xe0, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
calldatacopy(0xc0, 0, length)
r := mload(0xe0)
}
}
}