aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/analysis/ConstantEvaluator.cpp16
-rw-r--r--libsolidity/analysis/ConstantEvaluator.h7
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp30
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)