#6981 crash in checkvaarg.cpp (with possible fix). Avoid segfault. Add SymbolDatabase::validate() to allow validating smyboldatabase
This commit is contained in:
parent
5ddc5c0798
commit
ba0859e838
|
@ -40,6 +40,8 @@ void CheckVaarg::va_start_argument()
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Scope* scope = symbolDatabase->functionScopes[i];
|
const Scope* scope = symbolDatabase->functionScopes[i];
|
||||||
const Function* function = scope->function;
|
const Function* function = scope->function;
|
||||||
|
if (!function)
|
||||||
|
continue;
|
||||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
if (!tok->scope()->isExecutable())
|
if (!tok->scope()->isExecutable())
|
||||||
tok = tok->scope()->classEnd;
|
tok = tok->scope()->classEnd;
|
||||||
|
|
|
@ -1425,6 +1425,25 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
return false;
|
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
|
bool Variable::isPointerArray() const
|
||||||
{
|
{
|
||||||
return isArray() && nameToken() && nameToken()->previous() && (nameToken()->previous()->str() == "*");
|
return isArray() && nameToken() && nameToken()->previous() && (nameToken()->previous()->str() == "*");
|
||||||
|
|
|
@ -1007,6 +1007,11 @@ public:
|
||||||
|
|
||||||
bool isCPP() const;
|
bool isCPP() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Do a sanity check
|
||||||
|
*/
|
||||||
|
void validate() const;
|
||||||
|
|
||||||
/** Set valuetype in provided tokenlist */
|
/** Set valuetype in provided tokenlist */
|
||||||
static void setValueTypeInTokenList(Token *tokens);
|
static void setValueTypeInTokenList(Token *tokens);
|
||||||
|
|
||||||
|
@ -1022,6 +1027,11 @@ private:
|
||||||
const Type *findTypeInNested(const Token *tok, const Scope *startScope) const;
|
const Type *findTypeInNested(const Token *tok, const Scope *startScope) const;
|
||||||
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
|
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
|
||||||
Function *findFunctionInScope(const Token *func, const Scope *ns);
|
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*/
|
/** 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;
|
bool isReservedName(const std::string& iName) const;
|
||||||
|
|
|
@ -9840,6 +9840,8 @@ void Tokenizer::createSymbolDatabase()
|
||||||
{
|
{
|
||||||
if (!_symbolDatabase)
|
if (!_symbolDatabase)
|
||||||
_symbolDatabase = new SymbolDatabase(this, _settings, _errorLogger);
|
_symbolDatabase = new SymbolDatabase(this, _settings, _errorLogger);
|
||||||
|
if (_settings->debug)
|
||||||
|
_symbolDatabase->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::deleteSymbolDatabase()
|
void Tokenizer::deleteSymbolDatabase()
|
||||||
|
|
|
@ -1982,7 +1982,7 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int
|
||||||
break;
|
break;
|
||||||
if (parent->str() == "?") {
|
if (parent->str() == "?") {
|
||||||
if (parent->astOperand2() != p)
|
if (parent->astOperand2() != p)
|
||||||
parent = NULL;
|
parent = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,7 @@ private:
|
||||||
|
|
||||||
void testautovar_return2() {
|
void testautovar_return2() {
|
||||||
check("class Fred {\n"
|
check("class Fred {\n"
|
||||||
" int* func1()\n"
|
" int* func1();\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"int* Fred::func1()\n"
|
"int* Fred::func1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -876,7 +876,6 @@ private:
|
||||||
" return foo();\n"
|
" return foo();\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// Don't crash with function in unknown scope (#4076)
|
// Don't crash with function in unknown scope (#4076)
|
||||||
check("X& a::Bar() {}"
|
check("X& a::Bar() {}"
|
||||||
"X& foo() {"
|
"X& foo() {"
|
||||||
|
|
|
@ -50,6 +50,7 @@ private:
|
||||||
TEST_CASE(va_end_missing);
|
TEST_CASE(va_end_missing);
|
||||||
TEST_CASE(va_list_usedBeforeStarted);
|
TEST_CASE(va_list_usedBeforeStarted);
|
||||||
TEST_CASE(va_start_subsequentCalls);
|
TEST_CASE(va_start_subsequentCalls);
|
||||||
|
TEST_CASE(unknownFunctionScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrongParameterTo_va_start() {
|
void wrongParameterTo_va_start() {
|
||||||
|
@ -227,6 +228,15 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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)
|
REGISTER_TEST(TestVaarg)
|
||||||
|
|
Loading…
Reference in New Issue