No calldata bounds checks
- Dominant language
- Haskell
- Stars
- 113
- Forks
- 9
- Avg merge
- 4d 9h
- Merged PRs (30d)
- 1
Description
BUG: generated dispatch validates only the static ABI head. Dynamic offsets,
lengths and element regions are not checked against calldatasize().
EVM calldata reads outside the supplied input yield zeros, so malformed calls can succeed with values the caller never supplied.
```solidity
import std.{*};
import std.dispatch.{*};
contract MalformedDynamicCalldata {
public function echoBytes(value: memory(bytes)) -> memory(bytes) {
return value;
}
public function arrayAt(
items: calldata(array(uint256)),
index: uint256
) -> uint256 {
return items[index];
}
}
```
For comparision ordinary Solidity rejects the same truncated calldata.
```solidity
pragma solidity ^0.8.0;
contract MalformedDynamicCalldataReference {
function echoBytes(bytes memory value) public pure returns (bytes memory) {
return value;
}
function arrayAt(uint256[] calldata items, uint256 index)
public pure returns (uint256) {
return items[index];
}
}
```
SOLUTION: Introduce bounded ABI readers carrying start, cursor, and end positions.
Bounds checks are needed in these ABI paths:
- do_exec: establish the calldata payload range and validate the complete static head.
- CalldataWordReader.read/copyToMem/advance: enforce bounds and prevent pointer overflow centrally.
- Scalar decoders (uint256, bytes32, bytes4, bool, address): ensure each 32-byte word exists, preferably through the
reader.
- decodeBytesLike: validate the head, dynamic offset, length word, padded payload end, and arithmetic.
- Tuple/ABITuple decoders: validate head-offset arithmetic and dynamic tuple offsets.
- Memory DynArray decoder: validate the offset, length, element-head region, multiplication, and every element.
- Calldata array decoder: validate the offset and length word before creating its lazy handle.
- abiArrayLength: ensure the handle points to an available length word.
- abiArrayGet: validate index multiplication, complete element table/region, and dynamic element offsets.
- WordReader.copyToMem: ensure the entire source range exists before copying.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating do_exec, CalldataWordReader, WordReader, and the listed ABI decoders, then trace how generated dispatch establishes calldata ranges. Check malformed dynamic calldata cases such as truncated bytes and arrays, and verify every listed reader and decoder rejects missing words, overflowed ranges, and invalid offsets instead of returning zero-filled values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell, solidity
- Domain
- compilers, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100