Skip to content

Commit 2cdd3b2

Browse files
committed
Resolving Keccak-256: check if arguments are identifiers early.
Previously, the check on whether the optimization was useful gas wise was done before checking if the keccak256 opcode had identifier as arguments. Since the gas meter crashes when encountering certain Yul opcodes (create, dataoffset, etc.), this optimizer step crashed.
1 parent 3da3ffe commit 2cdd3b2

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Compiler Features:
1212
* SMTChecker: Add constraints to better correlate ``address(this).balance`` and ``msg.value``.
1313
* SMTChecker: Support the ``value`` option for external function calls.
1414
* Commandline Interface: Disallowed the ``--experimental-via-ir`` option to be used with Standard Json, Assembler and Linker modes.
15+
* Yul Optimizer: Fix a crash in LoadResolver, when ``keccak256`` has particular non-identifier arguments.
1516

1617

1718
Bugfixes:

libyul/optimiser/LoadResolver.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ void LoadResolver::tryEvaluateKeccak(
9797
std::vector<Expression> const& _arguments
9898
)
9999
{
100+
yulAssert(_arguments.size() == 2, "");
101+
Identifier const* memoryKey = std::get_if<Identifier>(&_arguments.at(0));
102+
Identifier const* length = std::get_if<Identifier>(&_arguments.at(1));
103+
104+
if (!memoryKey || !length)
105+
return;
106+
100107
// The costs are only correct for hashes of 32 bytes or 1 word (when rounded up).
101108
GasMeter gasMeter{
102109
dynamic_cast<EVMDialect const&>(m_dialect),
@@ -122,13 +129,6 @@ void LoadResolver::tryEvaluateKeccak(
122129
if (costOfLiteral > costOfKeccak)
123130
return;
124131

125-
yulAssert(_arguments.size() == 2, "");
126-
Identifier const* memoryKey = std::get_if<Identifier>(&_arguments.at(0));
127-
Identifier const* length = std::get_if<Identifier>(&_arguments.at(1));
128-
129-
if (!memoryKey || !length)
130-
return;
131-
132132
auto memoryValue = util::valueOrNullptr(m_memory, memoryKey->name);
133133
if (memoryValue && inScope(*memoryValue))
134134
{
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This test used to crash: https://github.com/ethereum/solidity/issues/11801
2+
{
3+
for {} addmod(keccak256(0x0,create(0x0, 0x0, 0x0)), 0x0, 0x0) {} {}
4+
}
5+
// ----
6+
// step: loadResolver
7+
//
8+
// {
9+
// for { }
10+
// addmod(keccak256(0x0, create(0x0, 0x0, 0x0)), 0x0, 0x0)
11+
// { }
12+
// { }
13+
// }

0 commit comments

Comments
 (0)