uninitvar: handling arrays in non-executionpath checker

This commit is contained in:
Daniel Marjamäki 2015-07-23 14:51:38 +02:00
parent ce9272a4ed
commit 0b81a267f4
3 changed files with 65 additions and 63 deletions

View File

@ -1058,7 +1058,7 @@ void CheckUninitVar::checkScope(const Scope* scope)
{
for (std::list<Variable>::const_iterator i = scope->varlist.begin(); i != scope->varlist.end(); ++i) {
if ((_tokenizer->isCPP() && i->type() && !i->isPointer() && i->type()->needInitialization != Type::True) ||
i->isStatic() || i->isExtern() || i->isArray() || i->isReference())
i->isStatic() || i->isExtern() || i->isReference())
continue;
// don't warn for try/catch exception variable
@ -1077,18 +1077,33 @@ void CheckUninitVar::checkScope(const Scope* scope)
continue;
}
if (i->isArray()) {
const Token *tok = i->nameToken()->next();
while (Token::simpleMatch(tok->link(), "] ["))
tok = tok->link()->next();
if (Token::simpleMatch(tok->link(), "] ="))
continue;
}
bool stdtype = _tokenizer->isC();
const Token* tok = i->typeStartToken();
for (; tok && tok->str() != ";" && tok->str() != "<"; tok = tok->next()) {
if (tok->isStandardType())
stdtype = true;
}
if (i->isArray() && !stdtype)
continue;
while (tok && tok->str() != ";")
tok = tok->next();
if (!tok)
continue;
if (i->isArray()) {
Alloc alloc = ARRAY;
checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, "");
continue;
}
if (stdtype || i->isPointer()) {
Alloc alloc = NO_ALLOC;
checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, "");

View File

@ -57,7 +57,7 @@ public:
void check();
void checkScope(const Scope* scope);
void checkStruct(const Token *tok, const Variable &structvar);
enum Alloc { NO_ALLOC, NO_CTOR_CALL, CTOR_CALL };
enum Alloc { NO_ALLOC, NO_CTOR_CALL, CTOR_CALL, ARRAY };
bool checkScopeForVariable(const Token *tok, const Variable& var, bool* const possibleInit, bool* const noreturn, Alloc* const alloc, const std::string &membervar);
bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar);
bool checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors);
@ -96,10 +96,10 @@ public:
void uninitdataError(const Token *tok, const std::string &varname);
void uninitvarError(const Token *tok, const std::string &varname);
void uninitvarError(const Token *tok, const std::string &varname, Alloc alloc) {
if (alloc == NO_ALLOC)
uninitvarError(tok, varname);
else
if (alloc == NO_CTOR_CALL || alloc == CTOR_CALL)
uninitdataError(tok, varname);
else
uninitvarError(tok, varname);
}
void uninitStructMemberError(const Token *tok, const std::string &membername);

View File

@ -1248,19 +1248,17 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar("int f()\n"
"{\n"
checkUninitVar2("int f() {\n"
" char a[10];\n"
" char c = *a;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar("int f()\n"
"{\n"
checkUninitVar2("int f() {\n"
" char a[SIZE+10];\n"
" char c = *a;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVarB("int f()\n"
"{\n"
@ -1304,26 +1302,23 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void f()\n"
"{\n"
checkUninitVar2("void f() {\n"
" char s[20];\n"
" strcpy(s2, s);\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void f()\n"
"{\n"
checkUninitVar2("void f() {\n"
" char s[20];\n"
" strcat(s, \"abc\");\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void f()\n"
"{\n"
checkUninitVar2("void f() {\n"
" char s[20];\n"
" strchr(s, ' ');\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVarB("void foo()\n"
"{\n"
@ -1393,12 +1388,12 @@ private:
ASSERT_EQUALS("", errout.str());
// ticket #3344
checkUninitVar("void f(){\n"
checkUninitVar2("void f(){\n"
" char *strMsg = \"This is a message\";\n"
" char *buffer=(char*)malloc(128*sizeof(char));\n"
" strcpy(strMsg,buffer);\n"
" free(buffer);\n"
"}");
"}", "test.cpp", false);
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: buffer\n", errout.str());
// #3845
@ -1420,7 +1415,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar2("int foo() {\n"
checkUninitVar("int foo() {\n"
" int a[2][2];\n"
" return a[0][1];\n"
"}");
@ -1436,21 +1431,13 @@ private:
// alloc..
void uninitvar_alloc() {
checkUninitVar("void f()\n"
"{\n"
checkUninitVar2("void f() {\n"
" char *s = malloc(100);\n"
" strcat(s, \"abc\");\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n"
"{\n"
" char *s = malloc(100);\n"
" perror(s);\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n"
checkUninitVar2("void f()\n"
"{\n"
" char *s1 = new char[10];\n"
" char *s2 = new char[strlen(s1)];\n"