Closed Subway2023 closed 1 week ago
pragma solidity ^0.8.0;
contract C {
uint[][] a;
uint[] b;
function g() public returns (uint[] memory) {
uint[] storage c = b;
assembly {
mstore(0x40, 0)
}
return b;
}
}
have the same problem.
output
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000
output
000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020
``
Solidity uses memory offset 0x40
as free memory pointer for memory management (see https://docs.soliditylang.org/en/v0.8.26/assembly.html#memory-management). Furthermore, it relies on being able to use memory offsets 0-64 as scratch space and memory offset 0x60
as zero pointer. Manually interfering with the free memory pointer results (setting it to values below its initial value) generally results in undefined behaviour. Furthermore, memory cannot be assumed to be zeroed before a first write to it. In the given cases in particular, the value read from memPtr
, so the value in storedValue
already is undefined. It will probably be zero, which means that the subsequent write to 0x40
sets the free memory pointer to an invalid state. Now preparing returndata results in overlapping reads and write to memory for ABI encoding the returndata.
To produce consistent behaviour you generally need to respect Solidity's memory model within inline assembly, if you mix assembly and high-level code.
Environment
Steps to Reproduce
Legacy Codegen
output
IR-based Codegen
Why is there a difference in the return values? Shouldn't they all be 0?