Hey everyone,
For educational purposes, I got asked to provide an example of how an incorrect application of the memory-safe annotation might result in incorrect behavior by the Solidity compiler. we’re looking for sample code which:
-
incorrectly uses the memory-safe annotation that compiles and runs
-
upon removal of the incorrect memory-safe annotation, still compiles and runs (with the same compilation flags), but produces a different result
the only difference between the two trials should be removing the “memory-safe” annotation.
I came up with the following code:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
contract WithoutMemorySafe {
// Compute twice the sum of twenty squared parameters
function g(
uint256 x0,
uint256 x1,
uint256 x2,
uint256 x3,
uint256 x4,
uint256 x5,
uint256 x6,
uint256 x7,
uint256 x8,
uint256 x9,
uint256 x10,
uint256 x11,
uint256 x12,
uint256 x13,
uint256 x14,
uint256 x15,
uint256 x16,
uint256 x17,
uint256 x18,
uint256 x19
) public pure returns (uint256 result) {
assembly {
{
let u0 := arg(x0)
let u1 := arg(x1)
let u2 := arg(x2)
let u3 := arg(x3)
let u4 := arg(x4)
let u5 := arg(x5)
let u6 := arg(x6)
let u7 := arg(x7)
let u8 := arg(x8)
let u9 := arg(x9)
let u10 := arg(x10)
let u11 := arg(x11)
let u12 := arg(x12)
let u13 := arg(x13)
let u14 := arg(x14)
let u15 := arg(x15)
let u16 := arg(x16)
let u17 := arg(x17)
let u18 := arg(x18)
let u19 := arg(x19)
result := sum(u19, u18, u17, u16, u15, u14, u13, u12, u11, u10, u9, u8, u7, u6, u5, u4, u3, u2, u1, u0)
}
// Compute twice the square of an element
function arg(i) -> x {
let s := mul(i, i)
x := add(s, s)
}
function sum(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) ->
output
{
// Changes the behavior here
mstore(0x80, 999)
let temp := add(a0, a1)
temp := add(temp, a2)
temp := add(temp, a3)
temp := add(temp, a4)
temp := add(temp, a5)
temp := add(temp, a6)
temp := add(temp, a7)
temp := add(temp, a8)
temp := add(temp, a9)
temp := add(temp, a10)
temp := add(temp, a11)
temp := add(temp, a12)
temp := add(temp, a13)
temp := add(temp, a14)
temp := add(temp, a15)
temp := add(temp, a16)
temp := add(temp, a17)
temp := add(temp, a18)
temp := add(temp, a19)
output := temp
}
}
}
}
It compiles with solc 0.8.20 using the IR pipeline. Now, I need to remove all the non-intrinsic call and still have a code that satisfies the conditions. But now I am stuck.
Any help, insights is more than welcomed.