solidity icon indicating copy to clipboard operation
solidity copied to clipboard

Unsafe type conversions with the IR codegen

Open hedgar2017 opened this issue 9 months ago • 1 comments

Description

With legacy codegen, when uint40 is returned from a function, the value is truncated. In the code below, if a value larger than uint40 is passed to getNumber, it is truncated to 40 bits. This means that the results of getNumber(0) and getNumber(2**40) are the same.

With viaIR codegen, the value is not truncated and some garbage remains in memory. Thus, the actual index accessed in the numbers array is not correct, so executing getNumber(2**40) results in an 'Array index out of bound' panic error.

Environment

  • Compiler version: 0.8.25
  • Target EVM version (as per compiler settings): default
  • Operating system: MacOS 14 Sonoma

Steps to Reproduce

contract Foo {
    uint256[] internal numbers;

    function addNumber(uint256 number) public {
        numbers.push(number);
    }

    function getNumber(uint256 index) public view returns (uint256) {
        return numbers[_convertToUint40(index)];
    }

    function _convertToUint40(uint256 n) internal pure returns (uint40 result) {
        assembly {
            result := n
        }
    }
}

hedgar2017 avatar May 23 '24 20:05 hedgar2017