From 8b3673d34eb54937bada096c4d8db9c2d4d67b1b Mon Sep 17 00:00:00 2001 From: rodiazet Date: Fri, 24 Jan 2025 11:22:31 +0100 Subject: [PATCH] eof: Disallow EOF builtins in inline assembly. --- libyul/backends/evm/EVMDialect.cpp | 86 ++++++++++--------- .../invalid/eof/eof_builtins_disallowed.sol | 15 ++++ ...builtins_disallowed_in_inline_assembly.sol | 16 ++++ 3 files changed, 75 insertions(+), 42 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 74599eb1c449..611e95c39d72 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -381,50 +381,51 @@ std::vector> createBuiltins(langutil::EVMVe } else // EOF context { - builtins.emplace_back(createFunction( - "auxdataloadn", - 1, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), - {LiteralKind::Number}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - yulAssert(_call.arguments.size() == 1); - Literal const* literal = std::get_if(&_call.arguments.front()); - yulAssert(literal, ""); - yulAssert(literal->value.value() <= std::numeric_limits::max()); - _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); - } - )); - - builtins.emplace_back(createFunction( - "eofcreate", - 5, - 1, - EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), - ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), - {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, - []( - FunctionCall const& _call, - AbstractAssembly& _assembly, - BuiltinContext& context - ) { - yulAssert(_call.arguments.size() == 5); - Literal const* literal = std::get_if(&_call.arguments.front()); - auto const formattedLiteral = formatLiteral(*literal); - yulAssert(!util::contains(formattedLiteral, '.')); - auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); - yulAssert(containerID != nullptr); - yulAssert(*containerID <= std::numeric_limits::max()); - _assembly.appendEOFCreate(static_cast(*containerID)); - } + if (_objectAccess) + { + builtins.emplace_back(createFunction( + "auxdataloadn", + 1, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::DATALOADN), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::DATALOADN), + {LiteralKind::Number}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& + ) { + yulAssert(_call.arguments.size() == 1); + Literal const* literal = std::get_if(&_call.arguments.front()); + yulAssert(literal, ""); + yulAssert(literal->value.value() <= std::numeric_limits::max()); + _assembly.appendAuxDataLoadN(static_cast(literal->value.value())); + } )); - if (_objectAccess) + builtins.emplace_back(createFunction( + "eofcreate", + 5, + 1, + EVMDialect::sideEffectsOfInstruction(evmasm::Instruction::EOFCREATE), + ControlFlowSideEffects::fromInstruction(evmasm::Instruction::EOFCREATE), + {LiteralKind::String, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + []( + FunctionCall const& _call, + AbstractAssembly& _assembly, + BuiltinContext& context + ) { + yulAssert(_call.arguments.size() == 5); + Literal const* literal = std::get_if(&_call.arguments.front()); + auto const formattedLiteral = formatLiteral(*literal); + yulAssert(!util::contains(formattedLiteral, '.')); + auto const* containerID = valueOrNullptr(context.subIDs, formattedLiteral); + yulAssert(containerID != nullptr); + yulAssert(*containerID <= std::numeric_limits::max()); + _assembly.appendEOFCreate(static_cast(*containerID)); + } + )); + builtins.emplace_back(createFunction( "returncontract", 3, @@ -448,6 +449,7 @@ std::vector> createBuiltins(langutil::EVMVe _assembly.appendReturnContract(static_cast(*containerID)); } )); + } } yulAssert( ranges::all_of(builtins, [](std::optional const& _builtinFunction){ diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol new file mode 100644 index 000000000000..617aeff98929 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed.sol @@ -0,0 +1,15 @@ +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: legacy +// ---- +// DeclarationError 7223: (75-84): Builtin function "eofcreate" is only available in EOF. +// DeclarationError 7223: (114-128): Builtin function "returncontract" is only available in EOF. +// DeclarationError 7223: (149-161): Builtin function "auxdataloadn" is only available in EOF. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol new file mode 100644 index 000000000000..a2a6540efde5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/eof/eof_builtins_disallowed_in_inline_assembly.sol @@ -0,0 +1,16 @@ +// TODO: They should be available in some way in the context of inline assembly. For now it's disallowed them. +contract C { + function f() view public { + assembly { + eofcreate("a", 0, 0, 0, 0) + returncontract("a", 0) + auxdataloadn(0) + } + } +} +// ==== +// bytecodeFormat: >=EOFv1 +// ---- +// DeclarationError 4619: (186-195): Function "eofcreate" not found. +// DeclarationError 4619: (225-239): Function "returncontract" not found. +// DeclarationError 4619: (260-272): Function "auxdataloadn" not found.