From e69d20e10bf040c78a98d42514453d990aa56217 Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Date: Mon, 11 May 2015 12:31:53 +0200
Subject: [PATCH] C++: Limit parsing of initializer clauses

...to prevent out of memory crash for generated tables.

Change-Id: I8f9f51829fcce5bccfe0dba8852023f8dd7d6e37
Task-number: QTCREATORBUG-14390
Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
---
 src/libs/3rdparty/cplusplus/Parser.cpp | 15 +++++++++++++--
 src/libs/3rdparty/cplusplus/Parser.h   |  2 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 4f44d614658..7c330ce3300 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -42,6 +42,7 @@
 #define CPLUSPLUS_NO_DEBUG_RULE
 #define MAX_EXPRESSION_DEPTH 100
 #define MAX_STATEMENT_DEPTH 100
+#define MAX_INITIALIZER_CLAUSE_DEPTH 2000
 
 using namespace CPlusPlus;
 
@@ -2785,6 +2786,8 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
     ExpressionListAST **expression_list_ptr = &node;
     ExpressionAST *expression = 0;
 
+    _initializerClauseDepth.push(1);
+
     if (parseInitializerClause0x(expression)) {
         *expression_list_ptr = new (_pool) ExpressionListAST;
         (*expression_list_ptr)->value = expression;
@@ -2793,7 +2796,11 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
         if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT && (LA(2) == T_COMMA || LA(2) == T_RBRACE || LA(2) == T_RPAREN))
             consumeToken(); // ### create an argument pack
 
-        while (LA() == T_COMMA && LA(2) != T_RBRACE) {
+        for (++_initializerClauseDepth.top();
+                LA() == T_COMMA
+                    && LA(2) != T_RBRACE
+                    && _initializerClauseDepth.top() <= MAX_INITIALIZER_CLAUSE_DEPTH;
+             ++_initializerClauseDepth.top()) {
             consumeToken(); // consume T_COMMA
 
             if (parseInitializerClause0x(expression)) {
@@ -2808,7 +2815,11 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
         }
     }
 
-    return true;
+    const bool result = _initializerClauseDepth.top() <= MAX_INITIALIZER_CLAUSE_DEPTH;
+    _initializerClauseDepth.pop();
+    if (!result)
+        warning(cursor(), "Reached parse limit for initializer clause");
+    return result;
 }
 
 bool Parser::parseBracedInitList0x(ExpressionAST *&node)
diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h
index 4a2a6dfb7e0..7f7f2d28c0f 100644
--- a/src/libs/3rdparty/cplusplus/Parser.h
+++ b/src/libs/3rdparty/cplusplus/Parser.h
@@ -27,6 +27,7 @@
 #include "TranslationUnit.h"
 #include "MemoryPool.h"
 #include <map>
+#include <stack>
 
 namespace CPlusPlus {
 
@@ -321,6 +322,7 @@ private:
     bool _inExpressionStatement: 1;
     int _expressionDepth;
     int _statementDepth;
+    std::stack<int> _initializerClauseDepth;
 
     MemoryPool _expressionStatementTempPool;
     std::map<unsigned, TemplateArgumentListEntry> _templateArgumentList;
-- 
GitLab