diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 0fc1e54a830..5b421704a49 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2146,18 +2146,18 @@ void SymbolDatabase::validateExecutableScopes() const } namespace { - const Function* getFunctionForArgumentvariable(const Variable * const var, const std::vector& functionScopes) + const Function* getFunctionForArgumentvariable(const Variable * const var) { - const std::size_t functions = functionScopes.size(); - for (std::size_t i = 0; i < functions; ++i) { - const Scope* const scope = functionScopes[i]; - const Function* const function = scope->function; - if (function) { - for (std::size_t arg=0; arg < function->argCount(); ++arg) { - if (var==function->getArgumentVar(arg)) - return function; + if (const Scope* scope = var->nameToken()->scope()) { + auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [&](const Function& function) { + for (std::size_t arg = 0; arg < function.argCount(); ++arg) { + if (var == function.getArgumentVar(arg)) + return true; } - } + return false; + }); + if (it != scope->functionList.end()) + return &*it; } return nullptr; } @@ -2169,10 +2169,9 @@ void SymbolDatabase::validateVariables() const const Variable * const var = *iter; if (var) { if (!var->scope()) { - const Function* function = getFunctionForArgumentvariable(var, functionScopes); - if (!var->isArgument() || (function && function->hasBody())) { + const Function* function = getFunctionForArgumentvariable(var); + if (!var->isArgument() || (!function || function->hasBody())) { // variables which only appear in a function declaration do not have a scope throw InternalError(var->nameToken(), "Analysis failed (variable without scope). If the code is valid then please report this failure.", InternalError::INTERNAL); - //std::cout << "!!!Variable found without scope: " << var->nameToken()->str() << std::endl; } } } @@ -2184,8 +2183,7 @@ void SymbolDatabase::validate() const if (mSettings.debugwarnings) { validateExecutableScopes(); } - // TODO - //validateVariables(); + validateVariables(); } void SymbolDatabase::clangSetVariables(const std::vector &variableList) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 1395caed76d..ffa0777ecf5 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1392,12 +1392,6 @@ class CPPCHECKLIB SymbolDatabase { */ void validate() const; - void validateExecutableScopes() const; - /** - * @brief Check variable list, e.g. variables w/o scope - */ - void validateVariables() const; - /** Set valuetype in provided tokenlist */ void setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens=nullptr); @@ -1465,6 +1459,12 @@ class CPPCHECKLIB SymbolDatabase { void setValueType(Token* tok, const Variable& var, const SourceLocation &loc = SourceLocation::current()); void setValueType(Token* tok, const Enumerator& enumerator, const SourceLocation &loc = SourceLocation::current()); + void validateExecutableScopes() const; + /** + * @brief Check variable list, e.g. variables w/o scope + */ + void validateVariables() const; + Tokenizer& mTokenizer; const Settings &mSettings; ErrorLogger *mErrorLogger; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 0680fcd3f47..a2dba01c5ea 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8406,6 +8406,9 @@ void Tokenizer::findGarbageCode() const else if (Token::Match(tok, "%assign% [") && Token::simpleMatch(tok->linkAt(1), "] ;")) syntaxError(tok, tok->str() + "[...];"); + else if (Token::Match(tok, "[({<] %assign%")) + syntaxError(tok); + // UNKNOWN_MACRO(return) if (tok->isKeyword() && Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% (")) unknownMacroError(tok->linkAt(1)->previous()); diff --git a/test/cli/fuzz-crash/crash-2490dbc1880f2d7883c1b634deee8da3805186f8 b/test/cli/fuzz-crash/crash-2490dbc1880f2d7883c1b634deee8da3805186f8 new file mode 100644 index 00000000000..60a55bed0b9 --- /dev/null +++ b/test/cli/fuzz-crash/crash-2490dbc1880f2d7883c1b634deee8da3805186f8 @@ -0,0 +1 @@ +i a;m t(=a[]);m e(){a[]=0} \ No newline at end of file diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 5a6187cb3ca..f52ba217473 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -1644,23 +1644,23 @@ class TestGarbage : public TestFixture { } void garbageCode205() { - checkCode("class CodeSnippetsEvent : public wxCommandEvent {\n" - "public :\n" - " CodeSnippetsEvent ( wxEventType commandType = wxEventType , int id = 0 ) ;\n" - " CodeSnippetsEvent ( const CodeSnippetsEvent & event ) ;\n" - "virtual wxEvent * Clone ( ) const { return new CodeSnippetsEvent ( * this ) ; }\n" - "private :\n" - " int m_SnippetID ;\n" - "} ;\n" - "const wxEventType wxEVT_CODESNIPPETS_GETFILELINKS = wxNewEventType ( )\n" - "CodeSnippetsEvent :: CodeSnippetsEvent ( wxEventType commandType , int id )\n" - ": wxCommandEvent ( commandType , id ) {\n" - "}\n" - "CodeSnippetsEvent :: CodeSnippetsEvent ( const CodeSnippetsEvent & Event )\n" - ": wxCommandEvent ( Event )\n" - ", m_SnippetID ( 0 ) {\n" - "}"); // don't crash - (void)errout_str(); // we are not interested in the output + ASSERT_THROW(checkCode("class CodeSnippetsEvent : public wxCommandEvent {\n" + "public :\n" + " CodeSnippetsEvent ( wxEventType commandType = wxEventType , int id = 0 ) ;\n" + " CodeSnippetsEvent ( const CodeSnippetsEvent & event ) ;\n" + "virtual wxEvent * Clone ( ) const { return new CodeSnippetsEvent ( * this ) ; }\n" + "private :\n" + " int m_SnippetID ;\n" + "} ;\n" + "const wxEventType wxEVT_CODESNIPPETS_GETFILELINKS = wxNewEventType ( )\n" + "CodeSnippetsEvent :: CodeSnippetsEvent ( wxEventType commandType , int id )\n" + ": wxCommandEvent ( commandType , id ) {\n" + "}\n" + "CodeSnippetsEvent :: CodeSnippetsEvent ( const CodeSnippetsEvent & Event )\n" + ": wxCommandEvent ( Event )\n" + ", m_SnippetID ( 0 ) {\n" + "}"), + InternalError); } void garbageCode206() {