From bdc2c63327fa52e80182f0ede34d2aee159207a9 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Thu, 28 May 2020 16:09:52 +0200 Subject: [PATCH] Output error when forward referencing constants in inline assembly --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 25 +++++++++++++------ .../const_forward_reference.sol | 8 ++++++ .../invalid/const_forward_reference.sol | 12 +++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/const_forward_reference.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/const_forward_reference.sol diff --git a/Changelog.md b/Changelog.md index 573d83e5b..ebde3000b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * Type Checker: Fix internal compiler error when accessing members of array slices. * Type Checker: Fix internal compiler error when trying to decode too large static arrays. * Type Checker: Fix wrong compiler error when referencing an overridden function without calling it. + * Type Checker: Fix internal compiler error when forward referencing non-literal constants from inline assembly. * NatSpec: DocString block is terminated when encountering an empty line. * Scanner: Fix bug when two empty NatSpec comments lead to scanning past EOL. * Code Generator: Trigger proper unimplemented errors on certain array copy operations. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e6694043c..afdc7c869 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -691,14 +691,6 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter.typeError(3224_error, _identifier.location, "Constant has no value."); return size_t(-1); } - else if (!var || !type(*var)->isValueType() || ( - dynamic_cast(var->value().get()) == nullptr && - type(*var->value())->category() != Type::Category::RationalNumber - )) - { - m_errorReporter.typeError(7615_error, _identifier.location, "Only direct number constants and references to such constants are supported by inline assembly."); - return size_t(-1); - } else if (_context == yul::IdentifierContext::LValue) { m_errorReporter.typeError(6252_error, _identifier.location, "Constant variables cannot be assigned to."); @@ -709,6 +701,23 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter.typeError(6617_error, _identifier.location, "The suffixes _offset and _slot can only be used on non-constant storage variables."); return size_t(-1); } + else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast(var->value().get())) + { + m_errorReporter.typeError( + 2249_error, + _identifier.location, + "Constant variables with non-literal values cannot be forward referenced from inline assembly." + ); + return size_t(-1); + } + else if (!var || !type(*var)->isValueType() || ( + !dynamic_cast(var->value().get()) && + type(*var->value())->category() != Type::Category::RationalNumber + )) + { + m_errorReporter.typeError(7615_error, _identifier.location, "Only direct number constants and references to such constants are supported by inline assembly."); + return size_t(-1); + } } if (requiresStorage) diff --git a/test/libsolidity/syntaxTests/inlineAssembly/const_forward_reference.sol b/test/libsolidity/syntaxTests/inlineAssembly/const_forward_reference.sol new file mode 100644 index 000000000..8c61d318d --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/const_forward_reference.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + assembly { + pop(add(add(1, 2), c)) + } + } + int constant c = 1; +} diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/const_forward_reference.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/const_forward_reference.sol new file mode 100644 index 000000000..b8d7c0212 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/const_forward_reference.sol @@ -0,0 +1,12 @@ +contract C { + function f() { + assembly { + c := add(add(1, 2), c) + } + } + int constant c = 0 + 1; +} +// ---- +// SyntaxError: (15-83): No visibility specified. Did you intend to add "public"? +// TypeError: (71-72): Constant variables with non-literal values cannot be forward referenced from inline assembly. +// TypeError: (51-52): Constant variables cannot be assigned to.