From 21dee1c8ba42d392d3f39dffdcffa9ee87c20a79 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 29 Sep 2020 16:23:45 +0200 Subject: [PATCH] Check for circular constants across contracts. --- libsolidity/analysis/PostTypeChecker.cpp | 37 +++++++++++++++++------- libsolidity/analysis/PostTypeChecker.h | 7 +++++ libsolidity/interface/CompilerStack.cpp | 2 ++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 47be22810..4699a0b14 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -38,6 +38,13 @@ bool PostTypeChecker::check(ASTNode const& _astRoot) return Error::containsOnlyWarnings(m_errorReporter.errors()); } +bool PostTypeChecker::finalize() +{ + for (auto& checker: m_checkers) + checker->finalize(); + return Error::containsOnlyWarnings(m_errorReporter.errors()); +} + bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition) { return callVisit(_contractDefinition); @@ -83,6 +90,11 @@ bool PostTypeChecker::visit(Identifier const& _identifier) return callVisit(_identifier); } +bool PostTypeChecker::visit(MemberAccess const& _memberAccess) +{ + return callVisit(_memberAccess); +} + bool PostTypeChecker::visit(StructDefinition const& _struct) { return callVisit(_struct); @@ -110,14 +122,7 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker ConstStateVarCircularReferenceChecker(ErrorReporter& _errorReporter): Checker(_errorReporter) {} - bool visit(ContractDefinition const&) override - { - solAssert(!m_currentConstVariable, ""); - solAssert(m_constVariableDependencies.empty(), ""); - return true; - } - - void endVisit(ContractDefinition const&) override + void finalize() override { solAssert(!m_currentConstVariable, ""); for (auto declaration: m_constVariables) @@ -128,9 +133,12 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker "The value of the constant " + declaration->name() + " has a cyclic dependency via " + identifier->name() + "." ); + } - m_constVariables.clear(); - m_constVariableDependencies.clear(); + bool visit(ContractDefinition const&) override + { + solAssert(!m_currentConstVariable, ""); + return true; } bool visit(VariableDeclaration const& _variable) override @@ -162,6 +170,15 @@ struct ConstStateVarCircularReferenceChecker: public PostTypeChecker::Checker return true; } + bool visit(MemberAccess const& _memberAccess) override + { + if (m_currentConstVariable) + if (auto var = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) + if (var->isConstant()) + m_constVariableDependencies[m_currentConstVariable].insert(var); + return true; + } + VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom) { auto visitor = [&](VariableDeclaration const& _variable, util::CycleDetector& _cycleDetector, size_t _depth) diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h index d3f23918c..c4745d279 100644 --- a/libsolidity/analysis/PostTypeChecker.h +++ b/libsolidity/analysis/PostTypeChecker.h @@ -54,6 +54,9 @@ public: { Checker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + + /// Called after all source units have been visited. + virtual void finalize() {} protected: langutil::ErrorReporter& m_errorReporter; }; @@ -63,6 +66,9 @@ public: bool check(ASTNode const& _astRoot); + /// Called after all source units have been visited. + bool finalize(); + private: bool visit(ContractDefinition const& _contract) override; void endVisit(ContractDefinition const& _contract) override; @@ -77,6 +83,7 @@ private: bool visit(FunctionCall const& _functionCall) override; bool visit(Identifier const& _identifier) override; + bool visit(MemberAccess const& _identifier) override; bool visit(StructDefinition const& _struct) override; void endVisit(StructDefinition const& _struct) override; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 58ac8abec..1dae2b00e 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -387,6 +387,8 @@ bool CompilerStack::analyze() for (Source const* source: m_sourceOrder) if (source->ast && !postTypeChecker.check(*source->ast)) noErrors = false; + if (!postTypeChecker.finalize()) + noErrors = false; } // Check that immutable variables are never read in c'tors and assigned