From 25c562da81b65a1c33a92d452f87879baf4dd283 Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 12 Mar 2024 15:32:53 +0100 Subject: [PATCH 1/4] Enable validateVariables(), fix fuzzing crash --- lib/symboldatabase.cpp | 17 +++++++--- lib/symboldatabase.h | 12 +++---- ...h-2490dbc1880f2d7883c1b634deee8da3805186f8 | 1 + test/testgarbage.cpp | 33 ++++++++++--------- 4 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 test/cli/fuzz-crash/crash-2490dbc1880f2d7883c1b634deee8da3805186f8 diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 4c056626ef1..be3a65d8e23 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2161,6 +2161,17 @@ namespace { } } } + 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; } } @@ -2172,9 +2183,8 @@ void SymbolDatabase::validateVariables() const if (var) { if (!var->scope()) { const Function* function = getFunctionForArgumentvariable(var, functionScopes); - if (!var->isArgument() || (function && function->hasBody())) { + if (!var->isArgument() || (!function || function->hasBody())) { 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; } } } @@ -2186,8 +2196,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 f718e695842..9d378298f7e 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1394,12 +1394,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); @@ -1467,6 +1461,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/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 639b931e7e0..25a1c698fd5 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -1625,22 +1625,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 + 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() { From bef87656cc5b901bf0af69af06866d08480efb4c Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 12 Mar 2024 15:56:58 +0100 Subject: [PATCH 2/4] syntaxError --- lib/tokenize.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index da1a6fd0456..dfd9ed8bc79 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8401,6 +8401,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()); From ad2e8a8db1bfce912776d84f35bea16ae842074d Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 12 Mar 2024 17:05:25 +0100 Subject: [PATCH 3/4] Simplify --- lib/symboldatabase.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index be3a65d8e23..d933c7711d8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2148,19 +2148,8 @@ 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) { @@ -2182,8 +2171,8 @@ 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())) { // exception for variables which only appear in a function declaration throw InternalError(var->nameToken(), "Analysis failed (variable without scope). If the code is valid then please report this failure.", InternalError::INTERNAL); } } From 4a280ed30c9db8ecc8eec79609ccd54e7f073804 Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 12 Mar 2024 17:06:14 +0100 Subject: [PATCH 4/4] Comment --- lib/symboldatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index d933c7711d8..82466c21e4c 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2172,7 +2172,7 @@ void SymbolDatabase::validateVariables() const if (var) { if (!var->scope()) { const Function* function = getFunctionForArgumentvariable(var); - if (!var->isArgument() || (!function || function->hasBody())) { // exception for variables which only appear in a function declaration + 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); } }