From cfe9c01bf84dcc3c2583729fb22ea29c20d2a88e Mon Sep 17 00:00:00 2001 From: Alexander Mai Date: Wed, 3 Feb 2016 21:52:02 +0100 Subject: [PATCH] #7257 segmentation fault in valueFlowSwitchVariable (invalid code). Correct SymbolDatabase::validateVariables() so it does not complain about function arguments for function without body --- lib/symboldatabase.cpp | 29 +++++++++++++++++++++++++++-- lib/valueflow.cpp | 3 ++- test/testgarbage.cpp | 5 +++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index c084c8961..4052c56e3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1390,11 +1390,36 @@ void SymbolDatabase::validateExecutableScopes() const } } +namespace { + const Function* getFunctionForArgumentvariable(const Variable * const var, const std::vector& functionScopes) + { + 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; + } + } + } + return nullptr; + } +} + void SymbolDatabase::validateVariables() const { for (std::vector::const_iterator iter = _variableList.begin(); iter!=_variableList.end(); ++iter) { - if (*iter && !(*iter)->scope()) { - throw InternalError((*iter)->nameToken(), "Analysis failed (variable without scope). If the code is valid then please report this failure.", InternalError::INTERNAL); + if (*iter) { + const Variable * const var = *iter; + if (!var->scope()) { + const Function* function = getFunctionForArgumentvariable(var, functionScopes); + 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; + } + } } } } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 1a1d0bbd1..90e045d63 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2206,7 +2206,8 @@ static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symbol errorLogger, settings); } - valueFlowForward(tok, vartok->variable()->scope()->classEnd, vartok->variable(), vartok->varId(), values, false, tokenlist, errorLogger, settings); + if (vartok->variable()->scope()) // #7257 + valueFlowForward(tok, vartok->variable()->scope()->classEnd, vartok->variable(), vartok->varId(), values, false, tokenlist, errorLogger, settings); } } } diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index e5998d41e..00b8076b9 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -224,6 +224,7 @@ private: TEST_CASE(garbageCode173); // #6781 TEST_CASE(garbageCode174); // #7356 TEST_CASE(garbageCode175); + TEST_CASE(garbageCode176); TEST_CASE(garbageValueFlow); TEST_CASE(garbageSymbolDatabase); TEST_CASE(garbageAST); @@ -1474,6 +1475,10 @@ private: " return t1 ,\n" "}"), InternalError); } + + void garbageCode176() { // #7527 + checkCode("class t { { struct } enum class f : unsigned { q } b ; operator= ( T ) { switch ( b ) { case f::q: } } { assert ( b ) ; } } { ; & ( t ) ( f::t ) ; } ;"); + } }; REGISTER_TEST(TestGarbage)