Index: src/sksl/SkSLParser.cpp |
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp |
index 2699d9c113d076dee0844196220ed0bff1734806..7eac0ce5679d5de60909e29afd8257c6dc910d27 100644 |
--- a/src/sksl/SkSLParser.cpp |
+++ b/src/sksl/SkSLParser.cpp |
@@ -73,6 +73,31 @@ |
namespace SkSL { |
+#define MAX_PARSE_DEPTH 50 |
+ |
+class AutoDepth { |
+public: |
+ AutoDepth(Parser* p) |
+ : fParser(p) { |
+ fParser->fDepth++; |
+ } |
+ |
+ ~AutoDepth() { |
+ fParser->fDepth--; |
+ } |
+ |
+ bool checkValid() { |
+ if (fParser->fDepth > MAX_PARSE_DEPTH) { |
+ fParser->error(fParser->peek().fPosition, "exceeded max parse depth"); |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+private: |
+ Parser* fParser; |
+}; |
+ |
Parser::Parser(std::string text, SymbolTable& types, ErrorReporter& errors) |
: fPushback(Position(-1, -1), Token::INVALID_TOKEN, "") |
, fTypes(types) |
@@ -920,6 +945,10 @@ std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() { |
/* LBRACE statement* RBRACE */ |
std::unique_ptr<ASTBlock> Parser::block() { |
+ AutoDepth depth(this); |
+ if (!depth.checkValid()) { |
+ return nullptr; |
+ } |
Token start; |
if (!this->expect(Token::LBRACE, "'{'", &start)) { |
return nullptr; |
@@ -959,6 +988,10 @@ std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() { |
/* assignmentExpression */ |
std::unique_ptr<ASTExpression> Parser::expression() { |
+ AutoDepth depth(this); |
+ if (!depth.checkValid()) { |
+ return nullptr; |
+ } |
return this->assignmentExpression(); |
} |