Unsafe type conversions with the IR codegen
- Dominant language
- C++
- Stars
- 25.7k
- Forks
- 6.2k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 29
Description
## 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
```solidity
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
}
}
}
```
Contributor guide
Research direction
Start by compiling and running the Solidity reproducer with legacy and viaIR code generation, focusing on _convertToUint40 and the getNumber(2**40) call. Trace the IR codegen handling of the assembly assignment and add or update a regression test so the viaIR result truncates to uint40 and matches legacy codegen without an out-of-bounds panic.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, solidity
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100