Skip to content

Commit ba0859e

Browse files
committed
danmar#6981 crash in checkvaarg.cpp (with possible fix). Avoid segfault. Add SymbolDatabase::validate() to allow validating smyboldatabase
1 parent 5ddc5c0 commit ba0859e

File tree

7 files changed

+45
-3
lines changed

7 files changed

+45
-3
lines changed

lib/checkvaarg.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ void CheckVaarg::va_start_argument()
4040
for (std::size_t i = 0; i < functions; ++i) {
4141
const Scope* scope = symbolDatabase->functionScopes[i];
4242
const Function* function = scope->function;
43+
if (!function)
44+
continue;
4345
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
4446
if (!tok->scope()->isExecutable())
4547
tok = tok->scope()->classEnd;

lib/symboldatabase.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,25 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
14251425
return false;
14261426
}
14271427

1428+
void SymbolDatabase::validate() const
1429+
{
1430+
const std::size_t functions = functionScopes.size();
1431+
for (std::size_t i = 0; i < functions; ++i) {
1432+
const Scope* scope = functionScopes[i];
1433+
if (scope->isExecutable()) {
1434+
const Function* function = scope->function;
1435+
if (!function) {
1436+
cppcheckError(nullptr);
1437+
}
1438+
}
1439+
}
1440+
}
1441+
1442+
void SymbolDatabase::cppcheckError(const Token *tok) const
1443+
{
1444+
throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL);
1445+
}
1446+
14281447
bool Variable::isPointerArray() const
14291448
{
14301449
return isArray() && nameToken() && nameToken()->previous() && (nameToken()->previous()->str() == "*");

lib/symboldatabase.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,11 @@ class CPPCHECKLIB SymbolDatabase {
10071007

10081008
bool isCPP() const;
10091009

1010+
/*
1011+
* @brief Do a sanity check
1012+
*/
1013+
void validate() const;
1014+
10101015
/** Set valuetype in provided tokenlist */
10111016
static void setValueTypeInTokenList(Token *tokens);
10121017

@@ -1022,6 +1027,11 @@ class CPPCHECKLIB SymbolDatabase {
10221027
const Type *findTypeInNested(const Token *tok, const Scope *startScope) const;
10231028
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
10241029
Function *findFunctionInScope(const Token *func, const Scope *ns);
1030+
/**
1031+
* Send error message to error logger about internal bug.
1032+
* @param tok the token that this bug concerns.
1033+
*/
1034+
void cppcheckError(const Token *tok) const __attribute__((noreturn));
10251035

10261036
/** Whether iName is a keyword as defined in http://en.cppreference.com/w/c/keyword and http://en.cppreference.com/w/cpp/keyword*/
10271037
bool isReservedName(const std::string& iName) const;

lib/tokenize.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9840,6 +9840,8 @@ void Tokenizer::createSymbolDatabase()
98409840
{
98419841
if (!_symbolDatabase)
98429842
_symbolDatabase = new SymbolDatabase(this, _settings, _errorLogger);
9843+
if (_settings->debug)
9844+
_symbolDatabase->validate();
98439845
}
98449846

98459847
void Tokenizer::deleteSymbolDatabase()

lib/valueflow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1982,7 +1982,7 @@ static void valueFlowForLoopSimplify(Token * const bodyStart, const unsigned int
19821982
break;
19831983
if (parent->str() == "?") {
19841984
if (parent->astOperand2() != p)
1985-
parent = NULL;
1985+
parent = nullptr;
19861986
break;
19871987
}
19881988
}

test/testautovariables.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ class TestAutoVariables : public TestFixture {
446446

447447
void testautovar_return2() {
448448
check("class Fred {\n"
449-
" int* func1()\n"
449+
" int* func1();\n"
450450
"}\n"
451451
"int* Fred::func1()\n"
452452
"{\n"
@@ -876,7 +876,6 @@ class TestAutoVariables : public TestFixture {
876876
" return foo();\n"
877877
"}");
878878
ASSERT_EQUALS("", errout.str());
879-
880879
// Don't crash with function in unknown scope (#4076)
881880
check("X& a::Bar() {}"
882881
"X& foo() {"

test/testvaarg.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class TestVaarg : public TestFixture {
5050
TEST_CASE(va_end_missing);
5151
TEST_CASE(va_list_usedBeforeStarted);
5252
TEST_CASE(va_start_subsequentCalls);
53+
TEST_CASE(unknownFunctionScope);
5354
}
5455

5556
void wrongParameterTo_va_start() {
@@ -227,6 +228,15 @@ class TestVaarg : public TestFixture {
227228
"}");
228229
ASSERT_EQUALS("", errout.str());
229230
}
231+
232+
void unknownFunctionScope() {
233+
check("void BG_TString::Format() {\n"
234+
" BG_TChar * f;\n"
235+
" va_start(args,f);\n"
236+
" BG_TString result(f);\n"
237+
"}");
238+
ASSERT_EQUALS("", errout.str());
239+
}
230240
};
231241

232242
REGISTER_TEST(TestVaarg)

0 commit comments

Comments
 (0)