diff options
-rw-r--r-- | libsolidity/analysis/ConstantEvaluator.cpp | 16 | ||||
-rw-r--r-- | libsolidity/analysis/ConstantEvaluator.h | 7 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 30 |
3 files changed, 44 insertions, 9 deletions
diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 50044eb6..cb8bbc05 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -77,18 +77,22 @@ void ConstantEvaluator::endVisit(Literal const& _literal) void ConstantEvaluator::endVisit(Identifier const& _identifier) { - VariableDeclaration const *variableDeclaration = dynamic_cast<VariableDeclaration const *>(_identifier.annotation().referencedDeclaration); + VariableDeclaration const* variableDeclaration = dynamic_cast<VariableDeclaration const*>(_identifier.annotation().referencedDeclaration); if (!variableDeclaration) return; if (!variableDeclaration->isConstant()) m_errorReporter.fatalTypeError(_identifier.location(), "Identifier must be declared constant."); ASTPointer<Expression> value = variableDeclaration->value(); - if (value) - { - if (!value->annotation().type) - ConstantEvaluator e(*value, m_errorReporter); + if (!value) + m_errorReporter.fatalTypeError(_identifier.location(), "Constant identifier declaration must have a constant value."); - _identifier.annotation().type = value->annotation().type; + if (!value->annotation().type) + { + if (m_depth > 32) + m_errorReporter.fatalTypeError(_identifier.location(), "Cyclic constant definition."); + ConstantEvaluator e(*value, m_errorReporter, m_depth + 1); } + + _identifier.annotation().type = value->annotation().type; } diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 42ccfe7e..6725d610 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -38,8 +38,9 @@ class TypeChecker; class ConstantEvaluator: private ASTConstVisitor { public: - ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter): - m_errorReporter(_errorReporter) + ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter, size_t _newDepth = 0): + m_errorReporter(_errorReporter), + m_depth(_newDepth) { _expr.accept(*this); } @@ -51,6 +52,8 @@ private: virtual void endVisit(Identifier const& _identifier); ErrorReporter& m_errorReporter; + /// Current recursion depth. + size_t m_depth; }; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index cedf7f3a..0d02ac34 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7366,7 +7366,35 @@ BOOST_AUTO_TEST_CASE(array_length_cannot_be_constant_function_parameter) } } )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal."); + CHECK_ERROR(text, TypeError, "Constant identifier declaration must have a constant value."); +} + +BOOST_AUTO_TEST_CASE(array_length_with_cyclic_constant) +{ + char const* text = R"( + contract C { + uint constant LEN = LEN; + function f() { + uint[LEN] a; + } + } + )"; + CHECK_ERROR(text, TypeError, "Cyclic constant definition."); +} + +BOOST_AUTO_TEST_CASE(array_length_with_complex_cyclic_constant) +{ + char const* text = R"( + contract C { + uint constant L2 = LEN - 10; + uint constant L1 = L2 / 10; + uint constant LEN = 10 + L1 * 5; + function f() { + uint[LEN] a; + } + } + )"; + CHECK_ERROR(text, TypeError, "Cyclic constant definition."); } BOOST_AUTO_TEST_CASE(array_length_with_pure_functions) |