Merge pull request #14198 from ethereum/disallow-immutable-initialization-in-try-catch

Disallow immutable initialization in try catch statements
This commit is contained in:
Nikola Matić 2023-05-09 15:37:14 +02:00 committed by GitHub
commit 347c966f08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 0 deletions

View File

@ -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.

View File

@ -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<CallableDeclaration const*>(_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)

View File

@ -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;
};
}

View File

@ -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.