aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ethannicholas <ethannicholas@google.com>2016-10-27 10:54:02 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-10-27 10:54:02 -0700
commitcad6416ccbf103648874b0f5fb615ec5ac798f14 (patch)
tree207d821d33a85111bfcd8303a9843cf532deb6c9
parent18fa6421e9cb7ac2ea6b1a97112a115d6643c0fc (diff)
Added skslc parse recursion limit
The fuzzer discovered that a long chain of left-parentheses would cause a stack overflow due to excessive recursion. While it is not in general possible to guarantee that we do not exceed stack limits (because the system can be configured with an arbitrarily small stack), setting a reasonable recursion limit will at least keep the fuzzer from continually finding more "bugs" like this. BUG=skia:5899 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2459573003 Review-Url: https://codereview.chromium.org/2459573003
-rw-r--r--src/sksl/SkSLParser.cpp33
-rw-r--r--src/sksl/SkSLParser.h6
2 files changed, 38 insertions, 1 deletions
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 2699d9c113..7eac0ce567 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();
}
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index d1ae0d0e9f..f9dcde244f 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -197,12 +197,16 @@ private:
bool identifier(std::string* dest);
-
void* fScanner;
YY_BUFFER_STATE fBuffer;
+ // current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
+ // stack on pathological inputs
+ int fDepth = 0;
Token fPushback;
SymbolTable& fTypes;
ErrorReporter& fErrors;
+
+ friend class AutoDepth;
};
} // namespace