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)
/* 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;
/* assignmentExpression */
std::unique_ptr<ASTExpression> Parser::expression() {
+ AutoDepth depth(this);
+ if (!depth.checkValid()) {
+ return nullptr;
+ }
return this->assignmentExpression();
}
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