#6981 crash in checkvaarg.cpp (with possible fix). Avoid segfault. Add SymbolDatabase::validate() to allow validating smyboldatabase

This commit is contained in:
Alexander Mai 2015-12-05 20:55:26 +01:00
parent 5ddc5c0798
commit ba0859e838
7 changed files with 45 additions and 3 deletions

View File

@ -40,6 +40,8 @@ void CheckVaarg::va_start_argument()
for (std::size_t i = 0; i < functions; ++i) {
const Scope* scope = symbolDatabase->functionScopes[i];
const Function* function = scope->function;
if (!function)
continue;
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (!tok->scope()->isExecutable())
tok = tok->scope()->classEnd;

View File

@ -1425,6 +1425,25 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
return false;
}
void SymbolDatabase::validate() const
{
const std::size_t functions = functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope* scope = functionScopes[i];
if (scope->isExecutable()) {
const Function* function = scope->function;
if (!function) {
cppcheckError(nullptr);
}
}
}
}
void SymbolDatabase::cppcheckError(const Token *tok) const
{
throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL);
}
bool Variable::isPointerArray() const
{
return isArray() && nameToken() && nameToken()->previous() && (nameToken()->previous()->str() == "*");

View File

@ -1007,6 +1007,11 @@ public:
bool isCPP() const;
/*
* @brief Do a sanity check
*/
void validate() const;
/** Set valuetype in provided tokenlist */
static void setValueTypeInTokenList(Token *tokens);
@ -1022,6 +1027,11 @@ private:
const Type *findTypeInNested(const Token *tok, const Scope *startScope) const;
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
Function *findFunctionInScope(const Token *func, const Scope *ns);
/**
* Send error message to error logger about internal bug.
* @param tok the token that this bug concerns.
*/
void cppcheckError(const Token *tok) const __attribute__((noreturn));
/** 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;

View File

@ -9840,6 +9840,8 @@ void Tokenizer::createSymbolDatabase()
{
if (!_symbolDatabase)
_symbolDatabase = new SymbolDatabase(this, _settings, _errorLogger);
if (_settings->debug)
_symbolDatabase->validate();
}
void Tokenizer::deleteSymbolDatabase()

View File

@ -1982,7 +1982,7 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int
break;
if (parent->str() == "?") {
if (parent->astOperand2() != p)
parent = NULL;
parent = nullptr;
break;
}
}

View File

@ -446,7 +446,7 @@ private:
void testautovar_return2() {
check("class Fred {\n"
" int* func1()\n"
" int* func1();\n"
"}\n"
"int* Fred::func1()\n"
"{\n"
@ -876,7 +876,6 @@ private:
" return foo();\n"
"}");
ASSERT_EQUALS("", errout.str());
// Don't crash with function in unknown scope (#4076)
check("X& a::Bar() {}"
"X& foo() {"

View File

@ -50,6 +50,7 @@ private:
TEST_CASE(va_end_missing);
TEST_CASE(va_list_usedBeforeStarted);
TEST_CASE(va_start_subsequentCalls);
TEST_CASE(unknownFunctionScope);
}
void wrongParameterTo_va_start() {
@ -227,6 +228,15 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
}
void unknownFunctionScope() {
check("void BG_TString::Format() {\n"
" BG_TChar * f;\n"
" va_start(args,f);\n"
" BG_TString result(f);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestVaarg)