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) { 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) || 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; continue;
// don't warn for try/catch exception variable // don't warn for try/catch exception variable
@ -1077,18 +1077,33 @@ void CheckUninitVar::checkScope(const Scope* scope)
continue; 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(); bool stdtype = _tokenizer->isC();
const Token* tok = i->typeStartToken(); const Token* tok = i->typeStartToken();
for (; tok && tok->str() != ";" && tok->str() != "<"; tok = tok->next()) { for (; tok && tok->str() != ";" && tok->str() != "<"; tok = tok->next()) {
if (tok->isStandardType()) if (tok->isStandardType())
stdtype = true; stdtype = true;
} }
if (i->isArray() && !stdtype)
continue;
while (tok && tok->str() != ";") while (tok && tok->str() != ";")
tok = tok->next(); tok = tok->next();
if (!tok) if (!tok)
continue; continue;
if (i->isArray()) {
Alloc alloc = ARRAY;
checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, "");
continue;
}
if (stdtype || i->isPointer()) { if (stdtype || i->isPointer()) {
Alloc alloc = NO_ALLOC; Alloc alloc = NO_ALLOC;
checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, ""); checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, "");

View File

@ -57,7 +57,7 @@ public:
void check(); void check();
void checkScope(const Scope* scope); void checkScope(const Scope* scope);
void checkStruct(const Token *tok, const Variable &structvar); 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 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 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); 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 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);
void uninitvarError(const Token *tok, const std::string &varname, Alloc alloc) { void uninitvarError(const Token *tok, const std::string &varname, Alloc alloc) {
if (alloc == NO_ALLOC) if (alloc == NO_CTOR_CALL || alloc == CTOR_CALL)
uninitvarError(tok, varname);
else
uninitdataError(tok, varname); uninitdataError(tok, varname);
else
uninitvarError(tok, varname);
} }
void uninitStructMemberError(const Token *tok, const std::string &membername); 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()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar("int f()\n" checkUninitVar2("int f() {\n"
"{\n" " char a[10];\n"
" char a[10];\n" " char c = *a;\n"
" char c = *a;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar("int f()\n" checkUninitVar2("int f() {\n"
"{\n" " char a[SIZE+10];\n"
" char a[SIZE+10];\n" " char c = *a;\n"
" char c = *a;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVarB("int f()\n" checkUninitVarB("int f()\n"
"{\n" "{\n"
@ -1304,26 +1302,23 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f() {\n"
"{\n" " char s[20];\n"
" char s[20];\n" " strcpy(s2, s);\n"
" strcpy(s2, s);\n" "};");
"};"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f() {\n"
"{\n" " char s[20];\n"
" char s[20];\n" " strcat(s, \"abc\");\n"
" strcat(s, \"abc\");\n" "};");
"};"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f() {\n"
"{\n" " char s[20];\n"
" char s[20];\n" " strchr(s, ' ');\n"
" strchr(s, ' ');\n" "};");
"};"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: s\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVarB("void foo()\n" checkUninitVarB("void foo()\n"
"{\n" "{\n"
@ -1393,12 +1388,12 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// ticket #3344 // ticket #3344
checkUninitVar("void f(){\n" checkUninitVar2("void f(){\n"
" char *strMsg = \"This is a message\";\n" " char *strMsg = \"This is a message\";\n"
" char *buffer=(char*)malloc(128*sizeof(char));\n" " char *buffer=(char*)malloc(128*sizeof(char));\n"
" strcpy(strMsg,buffer);\n" " strcpy(strMsg,buffer);\n"
" free(buffer);\n" " free(buffer);\n"
"}"); "}", "test.cpp", false);
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: buffer\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: buffer\n", errout.str());
// #3845 // #3845
@ -1420,10 +1415,10 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); 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" " int a[2][2];\n"
" return a[0][1];\n" " return a[0][1];\n"
"}"); "}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", "", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", "", errout.str());
// # 4740 // # 4740
@ -1436,25 +1431,17 @@ private:
// alloc.. // alloc..
void uninitvar_alloc() { void uninitvar_alloc() {
checkUninitVar("void f()\n" checkUninitVar2("void f() {\n"
"{\n" " char *s = malloc(100);\n"
" char *s = malloc(100);\n" " strcat(s, \"abc\");\n"
" strcat(s, \"abc\");\n" "};");
"};"); ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: s\n", errout.str());
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" "{\n"
" char *s = malloc(100);\n" " char *s1 = new char[10];\n"
" perror(s);\n" " char *s2 = new char[strlen(s1)];\n"
"};"); "};");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n"
"{\n"
" char *s1 = new char[10];\n"
" char *s2 = new char[strlen(s1)];\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s1\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s1\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar("void f()\n"