From d145f9ca7de8e5e4816b5200fc9076c0995000bf Mon Sep 17 00:00:00 2001 From: olabetskyi <153490942+olabetskyi@users.noreply.github.com> Date: Tue, 13 Feb 2024 11:14:37 +0200 Subject: [PATCH] FIX #12432: Crash in setValueTypeInTokenList() (#5978) --- lib/symboldatabase.cpp | 20 ++++++++++++-------- test/testsymboldatabase.cpp | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 040b88ed41e..32b9c921e73 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -737,15 +737,21 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() } else { tok = tok->link(); } - } else if (Token::Match(tok, "%name% (")) { - if (Token::simpleMatch(tok->linkAt(1), ") ;")) { + } else if (Token::Match(tok, "extern %type%")) { + const Token * ftok = tok->next(); + while (Token::Match(ftok, "%name%|*|&")) + ftok = ftok->next(); + if (!ftok || ftok->str() != "(") + continue; + ftok = ftok->previous(); + if (Token::simpleMatch(ftok->linkAt(1), ") ;")) { const Token *funcStart = nullptr; const Token *argStart = nullptr; const Token *declEnd = nullptr; - if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) { + if (isFunction(ftok, scope, &funcStart, &argStart, &declEnd)) { if (declEnd && declEnd->str() == ";") { bool newFunc = true; // Is this function already in the database? - auto range = scope->functionMap.equal_range(tok->str()); + auto range = scope->functionMap.equal_range(ftok->str()); for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { if (it->second->argsMatch(scope, it->second->argDef, argStart, emptyString, 0)) { newFunc = false; @@ -754,13 +760,12 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() } // save function prototype in database if (newFunc) { - Function function(tok, scope, funcStart, argStart); + Function function(ftok, scope, funcStart, argStart); if (function.isExtern()) { scope->addFunction(std::move(function)); tok = declEnd; } } - continue; } } } @@ -5930,8 +5935,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const const Scope *currScope = tok->scope(); while (currScope && currScope->isExecutable()) { if (const Function* f = currScope->findFunction(tok)) { - if (f->isExtern()) - return f; + return f; } if (currScope->functionOf) currScope = currScope->functionOf; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 7a4c7622b0c..1c42d76fdf9 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -270,7 +270,8 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(memberFunctionOfUnknownClassMacro2); TEST_CASE(memberFunctionOfUnknownClassMacro3); TEST_CASE(functionLinkage); - TEST_CASE(externalFunctionsInsideAFunction); // #12420 + TEST_CASE(externalFunctionsInsideAFunction); // #12420 + TEST_CASE(namespacedFunctionInsideExternBlock); // #12420 TEST_CASE(classWithFriend); @@ -2378,6 +2379,20 @@ class TestSymbolDatabase : public TestFixture { ASSERT(call && call->function() == f->function()); } + void namespacedFunctionInsideExternBlock() { + // Should not crash + GET_SYMBOL_DB("namespace N {\n" + " void f();\n" + "}\n" + "extern \"C\" {\n" + " void f() {\n" + " N::f();\n" + " }\n" + "}\n"); + + ASSERT(db && errout.str().empty()); + } + void classWithFriend() { GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };"); // 3 scopes: Global, 3 classes