argotorg / argotorg/solidity

Yul StackLimitEvader rejects high memoryguard boundaries with an ICE

Open
#16,836 0 comments 0 reactions 1 assignee Claimed by @clonker View on GitHub
bug :bug:
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
2d 19h
Merged PRs (30d)
29

Description

## Environment

- Compiler version: `0.8.36-develop.2026.6.25+commit.6deed02c` (argotorg/solidity `develop`, commit `6deed02c`, 2026-06-25)
- Built from source; Linux
- **Verified to reproduce on this commit.**

## Summary

`StackLimitEvader` asserts that the `memoryguard` boundary is below what appears
to be a 32-bit limit, but the expression lacks parentheses:
`reservedMemory < u256(1) << 32 - 1`. In C++, the subtraction binds before the
shift and the shift binds before the comparison, so this is parsed as
`reservedMemory < (u256(1) << 31)` rather than the intended
`reservedMemory < ((u256(1) << 32) - 1)`. The resulting assertion fires for a
normal Standard JSON Yul input using `memoryguard(0x80000000)`.

## Evidence

The guard at `libyul/optimiser/StackLimitEvader.cpp` is:

```cpp
yulAssert(reservedMemory < u256(1) << 32 - 1, "");
```

The later `requiredSlots` guard uses explicit parentheses for the intended
limit:

```cpp
yulAssert(requiredSlots < (uint64_t(1) << 32) - 1, "");
```

Reproducer:

```bash
solc --standard-json \
< repro_yul_memoryguard_high_boundary_ice.json
```

Output
```json
{
"errors": [
{
"component": "general",
"formattedMessage": "Uncaught exception:\n/solidity/libyul/optimiser/StackLimitEvader.cpp(203): Throw in function static void solidity::yul::StackLimitEvader::run(solidity::yul::OptimiserStepContext&, solidity::yul::Block&, const std::map >&)\nDynamic exception type: boost::wrapexcept\nstd::exception::what: Yul assertion failed\n[solidity::util::tag_comment*] = Yul assertion failed\n",
"message": "Uncaught exception:\n/solidity/libyul/optimiser/StackLimitEvader.cpp(203): Throw in function static void solidity::yul::StackLimitEvader::run(solidity::yul::OptimiserStepContext&, solidity::yul::Block&, const std::map >&)\nDynamic exception type: boost::wrapexcept\nstd::exception::what: Yul assertion failed\n[solidity::util::tag_comment*] = Yul assertion failed\n",
"severity": "error",
"type": "InternalCompilerError"
}
]
}
```

## Impact

A Yul input with an otherwise accepted `memoryguard` literal at or above
`0x80000000` can crash the optimizer with an internal compiler error instead of
producing output or a user-facing validation error.

## Recommendation

Parenthesize the intended limit, for example:

```cpp
yulAssert(reservedMemory < (u256(1) << 32) - 1, "");
```

Add a Standard JSON Yul regression test for `memoryguard(0x80000000)` and a
near-boundary value.

## Steps to reproduce

Save the source(s) below, then run:

```bash
solc --standard-json < repro_yul_memoryguard_high_boundary_ice.json
```

`repro_yul_memoryguard_high_boundary_ice.json`:

```json
{
"language": "Yul",
"sources": {
"main.yul": {
"content": "object \"O\" { code { mstore(0, memoryguard(0x80000000)) return(0, 32) } }"
}
},
"settings": {
"optimizer": {
"enabled": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode.object",
"irOptimized"
]
}
}
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.