From 9a87b587d52cf59ecb5d6f947023e951a7a8627a Mon Sep 17 00:00:00 2001 From: Nikola Matic Date: Tue, 9 May 2023 12:12:12 +0200 Subject: [PATCH] Disallow immutable initialization in try catch statements Trigger github --- Changelog.md | 1 + libsolidity/analysis/ImmutableValidator.cpp | 19 +++++++++ libsolidity/analysis/ImmutableValidator.h | 2 + .../immutable/try_catch_initialized.sol | 42 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol diff --git a/Changelog.md b/Changelog.md index 492197341..f00234d8b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * Antlr Grammar: Fix discrepancy with the parser, which allowed octal numbers. * Antlr Grammar: Fix of a discrepancy with the parser, which allowed numbers followed by an identifier with no whitespace. * Antlr Grammar: Stricter rules for function definitions. The grammar will no longer accept as valid free functions having specifiers which are exclusive to contract functions. + * Immutables: Disallow initialization of immutables in try/catch statements. * SMTChecker: Fix false positives in ternary operators that contain verification targets in its branches, directly or indirectly. diff --git a/libsolidity/analysis/ImmutableValidator.cpp b/libsolidity/analysis/ImmutableValidator.cpp index 485aa3fa2..8e89c49ab 100644 --- a/libsolidity/analysis/ImmutableValidator.cpp +++ b/libsolidity/analysis/ImmutableValidator.cpp @@ -132,6 +132,19 @@ bool ImmutableValidator::visit(WhileStatement const& _whileStatement) return false; } +bool ImmutableValidator::visit(TryStatement const& _tryStatement) +{ + ScopedSaveAndRestore constructorGuard{m_inTryStatement, true}; + + _tryStatement.externalCall().accept(*this); + + for (auto&& clause: _tryStatement.clauses()) + if (clause) + clause->accept(*this); + + return false; +} + void ImmutableValidator::endVisit(IdentifierPath const& _identifierPath) { if (auto const callableDef = dynamic_cast(_identifierPath.annotation().referencedDeclaration)) @@ -217,6 +230,12 @@ void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _va _expression.location(), "Cannot write to immutable here: Immutable variables cannot be initialized inside an if statement." ); + else if (m_inTryStatement) + m_errorReporter.typeError( + 4130_error, + _expression.location(), + "Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement." + ); else if (m_initializedStateVariables.count(&_variableReference)) { if (!read) diff --git a/libsolidity/analysis/ImmutableValidator.h b/libsolidity/analysis/ImmutableValidator.h index 452e91d7c..43a4b5dbf 100644 --- a/libsolidity/analysis/ImmutableValidator.h +++ b/libsolidity/analysis/ImmutableValidator.h @@ -55,6 +55,7 @@ private: bool visit(MemberAccess const& _memberAccess); bool visit(IfStatement const& _ifStatement); bool visit(WhileStatement const& _whileStatement); + bool visit(TryStatement const& _tryStatement); void endVisit(IdentifierPath const& _identifierPath); void endVisit(Identifier const& _identifier); void endVisit(Return const& _return); @@ -78,6 +79,7 @@ private: bool m_inLoop = false; bool m_inBranch = false; bool m_inCreationContext = true; + bool m_inTryStatement = false; }; } diff --git a/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol b/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol new file mode 100644 index 000000000..2d901a020 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol @@ -0,0 +1,42 @@ +contract A +{ + uint256 public immutable variable; + + constructor() + { + B b; + try b.foo(variable = 1) + { + variable = 2; + } + catch Panic(uint) + { + variable = 3; + } + catch Error(string memory) + { + variable = 4; + } + catch + { + variable = 5; + } + } +} + +contract B +{ + function foo(uint256) external pure + { + revert(); + } +} + +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError 4130: (108-116): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. +// TypeError 4130: (144-152): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. +// TypeError 4130: (216-224): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. +// TypeError 4130: (297-305): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. +// TypeError 4130: (357-365): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement.