diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 37712f4c4..be9e65c69 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -745,6 +745,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // save function prototype in database if (newFunc) { Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart); + if (!func) + break; if (Token::Match(argStart->link(), ") const| noexcept")) { int arg = 2; @@ -1658,6 +1660,9 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co if (!function) function = addGlobalFunctionDecl(scope, tok, argStart, funcStart); + if (!function) + return 0; + function->arg = argStart; function->token = funcStart; function->hasBody(true); @@ -1683,6 +1688,8 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, function.access = Public; // save the function name location + if (funcStart && isReservedName(funcStart->str())) + return 0; function.tokenDef = funcStart; function.isInline(false); @@ -3588,3 +3595,28 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n return const_cast(function); } + +//--------------------------------------------------------------------------- + +bool SymbolDatabase::isReservedName(const std::string& iName) const +{ + static const std::set c_keywords = make_container>() << + "auto" << "break" << "case" << "char" << "const" << "continue" << "default" << "do" << + "double" << "else" << "enum" << "extern" << "float" << "for" << "goto" << "if" << "inline" << + "int" << "long" << "register" << "restrict" << "return" << "short" << "signed" << "sizeof" << + "static" << "struct" << "switch" << "typedef" << "union" << "unsigned" << "void" << "volatile" << + "while"; + static const std::set cpp_keywords = make_container>() << + "alignas" << "alignof" << "and" << "and_eq" << "asm" << "auto" << "bitand" << "bitor" << "bool" << + "break" << "case" << "catch" << "char" << "char16_t" << "char32_t" << "class" << "compl" << + "concept" << "const" << "constexpr" << "const_cast" << "continue" << "decltype" << "default" << + "delete" << "do" << "double" << "dynamic_cast" << "else" << "enum" << "explicit" << "export" << + "extern" << "false" << "float" << "for" << "friend" << "goto" << "if" << "inline" << "int" << "long" << + "mutable" << "namespace" << "new" << "noexcept" << "not" << "not_eq" << "nullptr" << "operator" << + "or" << "or_eq" << "private" << "protected" << "public" << "register" << "reinterpret_cast" << + "requires" << "return" << "short" << "signed" << "sizeof" << "static" << "static_assert" << + "static_cast" << "struct" << "switch" << "template" << "this" << "thread_local" << "throw" << + "true" << "try" << "typedef" << "typeid" << "typename" << "union" << "unsigned" << "using" << + "virtual" << "void" << "volatile" << "wchar_t" << "while" << "xor" << "xor_eq"; + return (c_keywords.find(iName) != c_keywords.cend()) || (isCPP() && (cpp_keywords.find(iName) != cpp_keywords.cend())); +} diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 3fd02e2f9..c936684ec 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1005,6 +1005,9 @@ private: const Scope *findNamespace(const Token * tok, const Scope * scope) const; Function *findFunctionInScope(const Token *func, const Scope *ns); + /** Whether iName is a keyword as defined in http://en.cppreference.com/w/c/keyword and http://en.cppreference.com/w/cpp/keyword*/ + bool isReservedName(const std::string& iName) const; + const Tokenizer *_tokenizer; const Settings *_settings; diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index d5868f6b4..5239dbe94 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -78,6 +78,8 @@ private: TEST_CASE(garbageCode37); // #5166 TEST_CASE(garbageCode38); // #6666 TEST_CASE(garbageCode39); // #6686 + TEST_CASE(garbageCode40); // #6620 + TEST_CASE(garbageCode41); // #6685 TEST_CASE(garbageValueFlow); TEST_CASE(garbageSymbolDatabase); @@ -455,6 +457,14 @@ private: checkCode("({ (); strcat(strcat(() ()) ()) })"); } + void garbageCode40() { // #6620 + ASSERT_THROW(checkCode("{ ( ) () { virtual } ; { } E } A { : { } ( ) } * const ( ) const { }"), InternalError); + } + + void garbageCode41() { // #6685 + ASSERT_THROW(checkCode(" { } { return } *malloc(__SIZE_TYPE__ size); *memcpy(void n); static * const () { memcpy (*slot, 3); } { (); } { }"), InternalError); + } + void garbageValueFlow() { // #6089 const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n" diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index b55aa696f..e56792770 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -805,7 +805,7 @@ private: ASSERT_EQUALS("\n\n##file 0\n1: else { if ( ab ) { cd } else { ef } } gh\n", elseif(code)); // syntax error: assert there is no segmentation fault - ASSERT_EQUALS("\n\n##file 0\n1: else if ( x ) { }\n", elseif("else if (x) { }")); + ASSERT_THROW(elseif("else if (x) { }"), InternalError); { const char src[] = "void f(int g,int f) {\n" diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index d5ad4a01b..86e533989 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -1919,8 +1919,7 @@ private: } void symboldatabase36() { // ticket #4892 - check("void struct ( ) { if ( 1 ) } int main ( ) { }"); - ASSERT_EQUALS("", errout.str()); + ASSERT_THROW(check("void struct ( ) { if ( 1 ) } int main ( ) { }"), InternalError); } void symboldatabase37() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a22296861..c1f618fc3 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -1270,7 +1270,7 @@ private: void ifAddBraces15() { // ticket #2616 - unknown macro before if - ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false)); + ASSERT_THROW(tokenizeAndStringify("{A if(x)y();}", false), InternalError); } void ifAddBraces16() { // ticket # 2739 (segmentation fault) @@ -6145,7 +6145,7 @@ private: "operator ( ) ; " "}"; - ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); + ASSERT_EQUALS(result, tokenizeAndStringify(code, /*simplify=*/false, /*expand=*/true, /*platform=*/Settings::Unspecified, "test.c")); } void simplifyOperatorName2() {