From 7406dd8c941a60ba111dd4857dce0b99c54eef79 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Sun, 16 Jan 2022 05:46:20 -0600 Subject: [PATCH] Fix 10721: Crash in Tokenizer::simplifyTokenList1 (#3712) --- lib/tokenize.cpp | 31 +++++++++++++++++++++++++++++++ test/testsimplifytypedef.cpp | 15 +++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 0acdbaec4..4996285d5 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1057,6 +1057,7 @@ void Tokenizer::simplifyTypedef() int memberScope = 0; bool globalScope = false; int classLevel = spaceInfo.size(); + bool inTypeDef = false; std::string removed; std::string classPath; for (size_t i = 1; i < spaceInfo.size(); ++i) { @@ -1071,6 +1072,36 @@ void Tokenizer::simplifyTypedef() removed.clear(); + if (Token::simpleMatch(tok2, "typedef")) + inTypeDef = true; + + if (inTypeDef && Token::simpleMatch(tok2, ";")) + inTypeDef = false; + + // Check for variable declared with the same name + if (!inTypeDef && spaceInfo.size() == 1 && Token::Match(tok2->previous(), "%name%") && + !tok2->previous()->isKeyword()) { + Token* varDecl = tok2; + while (Token::Match(varDecl, "*|&|&&|const")) + varDecl = varDecl->next(); + if (Token::Match(varDecl, "%name% ;|,|)|=") && varDecl->str() == typeName->str()) { + // Skip to the next closing brace + if (Token::Match(varDecl, "%name% ) {")) { // is argument variable + tok2 = varDecl->linkAt(2)->next(); + } else { + tok2 = varDecl; + while (tok2 && !Token::simpleMatch(tok2, "}")) { + if (Token::Match(tok2, "(|{|[")) + tok2 = tok2->link(); + tok2 = tok2->next(); + } + } + if (!tok2) + break; + continue; + } + } + if (tok2->link()) { // Pre-check for performance // check for end of scope if (tok2->str() == "}") { diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 5263f1df3..9cfd1b9af 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -179,6 +179,7 @@ private: TEST_CASE(simplifyTypedef136); TEST_CASE(simplifyTypedef137); TEST_CASE(simplifyTypedef138); + TEST_CASE(simplifyTypedef139); TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -3006,6 +3007,20 @@ private: ASSERT_EQUALS("namespace foo { class Bar ; } class Baz ; namespace bar { class C : Baz { } ; }", tok(code)); } + void simplifyTypedef139() + { + const char code[] = "typedef struct c a;\n" + "struct {\n" + " a *b;\n" + "} * d;\n" + "void e(a *a) {\n" + " if (a < d[0].b) {}\n" + "}\n"; + ASSERT_EQUALS( + "struct Anonymous0 { struct c * b ; } ; struct Anonymous0 * d ; void e ( struct c * a ) { if ( a < d [ 0 ] . b ) { } }", + tok(code)); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"