aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp11
-rw-r--r--libsolidity/parsing/Parser.cpp32
-rw-r--r--libsolidity/parsing/Parser.h7
-rw-r--r--libsolidity/parsing/ParserBase.cpp13
-rw-r--r--libsolidity/parsing/ParserBase.h20
-rw-r--r--test/libjulia/Parser.cpp12
-rw-r--r--test/libsolidity/InlineAssembly.cpp14
8 files changed, 71 insertions, 39 deletions
diff --git a/Changelog.md b/Changelog.md
index ed004d8c..1ea3f6c8 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -13,6 +13,7 @@ Features:
Bugfixes:
* Assembly Parser: Be more strict about number literals.
+ * Assembly Parser: Limit maximum recursion depth.
* Parser: Enforce commas between array and tuple elements.
* Parser: Limit maximum recursion depth.
* Type Checker: Crash fix related to ``using``.
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 1dcc42b8..d84fe999 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -36,6 +36,7 @@ using namespace dev::solidity::assembly;
shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scanner)
{
+ m_recursionDepth = 0;
try
{
m_scanner = _scanner;
@@ -51,6 +52,7 @@ shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scann
assembly::Block Parser::parseBlock()
{
+ RecursionGuard recursionGuard(*this);
assembly::Block block = createWithLocation<Block>();
expectToken(Token::LBrace);
while (currentToken() != Token::RBrace)
@@ -62,6 +64,7 @@ assembly::Block Parser::parseBlock()
assembly::Statement Parser::parseStatement()
{
+ RecursionGuard recursionGuard(*this);
switch (currentToken())
{
case Token::Let:
@@ -158,6 +161,7 @@ assembly::Statement Parser::parseStatement()
assembly::Case Parser::parseCase()
{
+ RecursionGuard recursionGuard(*this);
assembly::Case _case = createWithLocation<assembly::Case>();
if (m_scanner->currentToken() == Token::Default)
m_scanner->next();
@@ -178,6 +182,7 @@ assembly::Case Parser::parseCase()
assembly::ForLoop Parser::parseForLoop()
{
+ RecursionGuard recursionGuard(*this);
ForLoop forLoop = createWithLocation<ForLoop>();
expectToken(Token::For);
forLoop.pre = parseBlock();
@@ -192,6 +197,7 @@ assembly::ForLoop Parser::parseForLoop()
assembly::Statement Parser::parseExpression()
{
+ RecursionGuard recursionGuard(*this);
Statement operation = parseElementaryOperation(true);
if (operation.type() == typeid(Instruction))
{
@@ -254,6 +260,7 @@ std::map<dev::solidity::Instruction, string> const& Parser::instructionNames()
assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
{
+ RecursionGuard recursionGuard(*this);
Statement ret;
switch (currentToken())
{
@@ -342,6 +349,7 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
+ RecursionGuard recursionGuard(*this);
VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
expectToken(Token::Let);
while (true)
@@ -366,6 +374,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration()
assembly::FunctionDefinition Parser::parseFunctionDefinition()
{
+ RecursionGuard recursionGuard(*this);
FunctionDefinition funDef = createWithLocation<FunctionDefinition>();
expectToken(Token::Function);
funDef.name = expectAsmIdentifier();
@@ -397,6 +406,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
{
+ RecursionGuard recursionGuard(*this);
if (_instruction.type() == typeid(Instruction))
{
solAssert(!m_julia, "Instructions are invalid in JULIA");
@@ -479,6 +489,7 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction)
TypedName Parser::parseTypedName()
{
+ RecursionGuard recursionGuard(*this);
TypedName typedName = createWithLocation<TypedName>();
typedName.name = expectAsmIdentifier();
if (m_julia)
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 92a614e0..cd0d6157 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -64,25 +64,6 @@ private:
SourceLocation m_location;
};
-/// Utility class that creates an error and throws an exception if the
-/// recursion depth is too deep.
-class Parser::RecursionGuard
-{
-public:
- explicit RecursionGuard(Parser& _parser):
- m_parser(_parser)
- {
- m_parser.increaseRecursionDepth();
- }
- ~RecursionGuard()
- {
- m_parser.decreaseRecursionDepth();
- }
-
-private:
- Parser& m_parser;
-};
-
ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
{
try
@@ -1543,19 +1524,6 @@ ASTPointer<ParameterList> Parser::createEmptyParameterList()
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
}
-void Parser::increaseRecursionDepth()
-{
- m_recursionDepth++;
- if (m_recursionDepth >= 4096)
- fatalParserError("Maximum recursion depth reached during parsing.");
-}
-
-void Parser::decreaseRecursionDepth()
-{
- solAssert(m_recursionDepth > 0, "");
- m_recursionDepth--;
-}
-
string Parser::currentTokenName()
{
Token::Value token = m_scanner->currentToken();
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 0f74880c..cfdfea7e 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -41,7 +41,6 @@ public:
private:
class ASTNodeFactory;
- class RecursionGuard;
struct VarDeclParserOptions
{
@@ -165,14 +164,8 @@ private:
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
ASTPointer<ParameterList> createEmptyParameterList();
- /// Increases the recursion depth and throws an exception if it is too deep.
- void increaseRecursionDepth();
- void decreaseRecursionDepth();
-
/// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.
bool m_insideModifier = false;
- /// Current recursion depth during parsing.
- size_t m_recursionDepth = 0;
};
}
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
index 5657c2c0..fe95b0fe 100644
--- a/libsolidity/parsing/ParserBase.cpp
+++ b/libsolidity/parsing/ParserBase.cpp
@@ -101,6 +101,19 @@ void ParserBase::expectToken(Token::Value _value)
m_scanner->next();
}
+void ParserBase::increaseRecursionDepth()
+{
+ m_recursionDepth++;
+ if (m_recursionDepth >= 3000)
+ fatalParserError("Maximum recursion depth reached during parsing.");
+}
+
+void ParserBase::decreaseRecursionDepth()
+{
+ solAssert(m_recursionDepth > 0, "");
+ m_recursionDepth--;
+}
+
void ParserBase::parserError(string const& _description)
{
m_errorReporter.parserError(SourceLocation(position(), position(), sourceName()), _description);
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index 48733fc1..fd0de0d1 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -41,6 +41,20 @@ public:
std::shared_ptr<std::string const> const& sourceName() const;
protected:
+ /// Utility class that creates an error and throws an exception if the
+ /// recursion depth is too deep.
+ class RecursionGuard
+ {
+ public:
+ explicit RecursionGuard(ParserBase& _parser): m_parser(_parser)
+ {
+ m_parser.increaseRecursionDepth();
+ }
+ ~RecursionGuard() { m_parser.decreaseRecursionDepth(); }
+ private:
+ ParserBase& m_parser;
+ };
+
/// Start position of the current token
int position() const;
/// End position of the current token
@@ -56,6 +70,10 @@ protected:
Token::Value advance();
///@}
+ /// Increases the recursion depth and throws an exception if it is too deep.
+ void increaseRecursionDepth();
+ void decreaseRecursionDepth();
+
/// Creates a @ref ParserError and annotates it with the current position and the
/// given @a _description.
void parserError(std::string const& _description);
@@ -67,6 +85,8 @@ protected:
std::shared_ptr<Scanner> m_scanner;
/// The reference to the list of errors and warning to add errors/warnings during parsing
ErrorReporter& m_errorReporter;
+ /// Current recursion depth during parsing.
+ size_t m_recursionDepth = 0;
};
}
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index e1bf5a3a..51070370 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -237,6 +237,18 @@ BOOST_AUTO_TEST_CASE(builtin_types)
BOOST_CHECK(successParse("{ let x:s256 := 1:s256 }"));
}
+BOOST_AUTO_TEST_CASE(recursion_depth)
+{
+ string input;
+ for (size_t i = 0; i < 20000; i++)
+ input += "{";
+ input += "let x:u256 := 0:u256";
+ for (size_t i = 0; i < 20000; i++)
+ input += "}";
+
+ CHECK_ERROR(input, ParserError, "recursion");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 8e1c304a..0debc66d 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -400,6 +400,20 @@ BOOST_AUTO_TEST_CASE(instruction_too_many_arguments)
CHECK_PARSE_ERROR("{ mul(1, 2, 3) }", ParserError, "Expected ')' (\"mul\" expects 2 arguments)");
}
+BOOST_AUTO_TEST_CASE(recursion_depth)
+{
+ string input;
+ for (size_t i = 0; i < 20000; i++)
+ input += "{";
+ input += "let x := 0";
+ for (size_t i = 0; i < 20000; i++)
+ input += "}";
+
+ CHECK_PARSE_ERROR(input, ParserError, "recursion");
+}
+
+
+
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(Printing)