From 3177d73fb06a312abf8fc2186789a7f1e6cd7967 Mon Sep 17 00:00:00 2001 From: Alexander Mai Date: Thu, 5 Nov 2015 19:00:08 +0100 Subject: [PATCH] #7089 segmentation fault (invalid code) in Tokenizer::simplifyTokenList1. Refactor some functions to accept argument as refernce instead of pointer --- lib/tokenize.cpp | 28 +++++++++++++++------------- lib/tokenize.h | 6 ++++++ test/testgarbage.cpp | 10 ++++++++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d4bc45a45..41ffaf3d3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2493,7 +2493,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map > *structMembers, + std::map >& structMembers, unsigned int *_varId) { Token *tok = *tok1; @@ -2507,7 +2507,7 @@ static void setVarIdStructMembers(Token **tok1, if (TemplateSimplifier::templateParameters(tok->next()) > 0) break; - std::map& members = (*structMembers)[struct_varid]; + std::map& members = structMembers[struct_varid]; const std::map::iterator it = members.find(tok->str()); if (it == members.end()) { members[tok->str()] = ++(*_varId); @@ -2521,11 +2521,11 @@ static void setVarIdStructMembers(Token **tok1, } -static void setVarIdClassDeclaration(Token * const startToken, - const std::map &variableId, - const unsigned int scopeStartVarId, - std::map > *structMembers, - unsigned int *_varId) +void Tokenizer::setVarIdClassDeclaration(Token * const startToken, + const std::map &variableId, + const unsigned int scopeStartVarId, + std::map >& structMembers, + unsigned int *_varId) { // end of scope const Token * const endToken = startToken->link(); @@ -2554,6 +2554,8 @@ static void setVarIdClassDeclaration(Token * const startToken, Token::Match(tok->link(), "}|) ,|{")) initListArgLastToken = tok->link(); } + if (!tok) + syntaxError(nullptr); // #7089 invalid code if (tok->str() == "{") { if (initList && !initListArgLastToken) initList = false; @@ -2595,7 +2597,7 @@ static void setVarIdClassFunction(const std::string &classname, Token * const startToken, const Token * const endToken, const std::map &varlist, - std::map > *structMembers, + std::map >& structMembers, unsigned int *_varId) { for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) { @@ -2699,7 +2701,7 @@ void Tokenizer::setVarId() setVarIdClassDeclaration(tok->link(), variableId, scopeStack.top().startVarid, - &structMembers, + structMembers, &_varId); } @@ -2819,7 +2821,7 @@ void Tokenizer::setVarId() const std::map::const_iterator it = variableId.find(tok->str()); if (it != variableId.end()) { tok->varId(it->second); - setVarIdStructMembers(&tok, &structMembers, &_varId); + setVarIdStructMembers(&tok, structMembers, &_varId); } } else if (Token::Match(tok, "::|. %name%")) { // Don't set varid after a :: or . token @@ -2876,7 +2878,7 @@ void Tokenizer::setVarId() if (tok2->link()) { if (tok2->str() == "{") { if (tok2->strAt(-1) == ")" || tok2->strAt(-2) == ")") - setVarIdClassFunction(classname, tok2, tok2->link(), thisClassVars, &structMembers, &_varId); + setVarIdClassFunction(classname, tok2, tok2->link(), thisClassVars, structMembers, &_varId); tok2 = tok2->link(); } else if (tok2->str() == "(" && tok2->link()->strAt(1) != "(") tok2 = tok2->link(); @@ -2920,7 +2922,7 @@ void Tokenizer::setVarId() // If this is a function implementation.. add it to funclist Token * start = startOfFunction(tok2); if (start) { - setVarIdClassFunction(classname, start, start->link(), thisClassVars, &structMembers, &_varId); + setVarIdClassFunction(classname, start, start->link(), thisClassVars, structMembers, &_varId); } // constructor with initializer list @@ -2934,7 +2936,7 @@ void Tokenizer::setVarId() tok3 = vartok->linkAt(1); } while (Token::Match(tok3, ")|} [:,] %name% (|{")); if (Token::Match(tok3, ")|} {")) { - setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, &structMembers, &_varId); + setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, structMembers, &_varId); } } } diff --git a/lib/tokenize.h b/lib/tokenize.h index 539cbaa66..b7e166129 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -716,6 +716,12 @@ private: void unsupportedTypedef(const Token *tok) const; + void setVarIdClassDeclaration(Token * const startToken, + const std::map &variableId, + const unsigned int scopeStartVarId, + std::map >& structMembers, + unsigned int *_varId); + public: /** Was there templates in the code? */ diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 2279b065a..2785b3f28 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -198,6 +198,7 @@ private: TEST_CASE(garbageCode147); // #7082 TEST_CASE(garbageCode148); // #7090 TEST_CASE(garbageCode149); // #7085 + TEST_CASE(garbageCode150); // #7089 TEST_CASE(garbageValueFlow); TEST_CASE(garbageSymbolDatabase); @@ -1185,6 +1186,15 @@ private: "}"); } + void garbageCode150() { // #7089 + ASSERT_THROW(checkCode("class A {\n" + " pl vFoo() {\n" + " A::\n" + " };\n" + " A::\n" + "}\n"), InternalError); + } + void garbageValueFlow() { // #6089 const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"