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.
This commit is contained in:
hrkrshnn 2021-09-06 12:02:55 +02:00
parent 3da3ffee5f
commit 2cdd3b2081
3 changed files with 21 additions and 7 deletions

View File

@ -12,6 +12,7 @@ Compiler Features:
* SMTChecker: Add constraints to better correlate ``address(this).balance`` and ``msg.value``.
* SMTChecker: Support the ``value`` option for external function calls.
* Commandline Interface: Disallowed the ``--experimental-via-ir`` option to be used with Standard Json, Assembler and Linker modes.
* Yul Optimizer: Fix a crash in LoadResolver, when ``keccak256`` has particular non-identifier arguments.
Bugfixes:

View File

@ -97,6 +97,13 @@ void LoadResolver::tryEvaluateKeccak(
std::vector<Expression> const& _arguments
)
{
yulAssert(_arguments.size() == 2, "");
Identifier const* memoryKey = std::get_if<Identifier>(&_arguments.at(0));
Identifier const* length = std::get_if<Identifier>(&_arguments.at(1));
if (!memoryKey || !length)
return;
// The costs are only correct for hashes of 32 bytes or 1 word (when rounded up).
GasMeter gasMeter{
dynamic_cast<EVMDialect const&>(m_dialect),
@ -122,13 +129,6 @@ void LoadResolver::tryEvaluateKeccak(
if (costOfLiteral > costOfKeccak)
return;
yulAssert(_arguments.size() == 2, "");
Identifier const* memoryKey = std::get_if<Identifier>(&_arguments.at(0));
Identifier const* length = std::get_if<Identifier>(&_arguments.at(1));
if (!memoryKey || !length)
return;
auto memoryValue = util::valueOrNullptr(m_memory, memoryKey->name);
if (memoryValue && inScope(*memoryValue))
{

View File

@ -0,0 +1,13 @@
// This test used to crash: https://github.com/ethereum/solidity/issues/11801
{
for {} addmod(keccak256(0x0,create(0x0, 0x0, 0x0)), 0x0, 0x0) {} {}
}
// ----
// step: loadResolver
//
// {
// for { }
// addmod(keccak256(0x0, create(0x0, 0x0, 0x0)), 0x0, 0x0)
// { }
// { }
// }