Uninitialized variables: Detect reading uninitialized data through array/pointer variable

This commit is contained in:
Daniel Marjamäki 2010-04-05 08:38:26 +02:00
parent 6db663f6de
commit d26a2cfc16
2 changed files with 35 additions and 6 deletions

View File

@ -1810,6 +1810,10 @@ private:
if (mode == 3 && (!c->pointer || c->alloc)) if (mode == 3 && (!c->pointer || c->alloc))
continue; continue;
// mode 4 : reading uninitialized array or pointer is invalid.
if (mode == 4 && (!c->array && !c->pointer))
continue;
CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner); CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner);
if (checkOther) if (checkOther)
{ {
@ -1855,9 +1859,9 @@ private:
* @param checks all available checks * @param checks all available checks
* @param tok variable token * @param tok variable token
*/ */
static void use_pointer(std::list<ExecutionPath *> &checks, const Token *tok) static bool use_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
{ {
use(checks, tok, 2); return use(checks, tok, 2);
} }
/** /**
@ -1865,11 +1869,23 @@ private:
* @param checks all available checks * @param checks all available checks
* @param tok variable token * @param tok variable token
*/ */
static void use_dead_pointer(std::list<ExecutionPath *> &checks, const Token *tok) static bool use_dead_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
{ {
use(checks, tok, 3); return use(checks, tok, 3);
} }
/**
* Using variable.. reading from uninitialized array or pointer data is invalid.
* Example: = x[0];
* @param checks all available checks
* @param tok variable token
*/
static bool use_array_or_pointer_data(std::list<ExecutionPath *> &checks, const Token *tok)
{
return use(checks, tok, 4);
}
/** declaring a variable */ /** declaring a variable */
void declare(std::list<ExecutionPath *> &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const void declare(std::list<ExecutionPath *> &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const
{ {
@ -1918,7 +1934,7 @@ private:
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
{ {
// Variable declaration.. // Variable declaration..
if (tok.str() != "return") if (tok.isName() && tok.str() != "return")
{ {
if (Token::Match(&tok, "enum %type% {")) if (Token::Match(&tok, "enum %type% {"))
return tok.tokAt(2)->link(); return tok.tokAt(2)->link();
@ -1989,7 +2005,13 @@ private:
!Token::Match(tok2->previous(), "&|::") && !Token::Match(tok2->previous(), "&|::") &&
!Token::simpleMatch(tok2->next(), "=")) !Token::simpleMatch(tok2->next(), "="))
{ {
bool foundError = use(checks, tok2); bool foundError;
if (tok2->next()->str() == "[")
foundError = use_array_or_pointer_data(checks, tok2);
else
foundError = use(checks, tok2);
// prevent duplicate error messages
if (foundError) if (foundError)
{ {
bailOutVar(checks, tok2->varId()); bailOutVar(checks, tok2->varId());

View File

@ -1671,6 +1671,13 @@ private:
"};\n"); "};\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s1\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s1\n", errout.str());
checkUninitVar("void f()\n"
"{\n"
" char *p = malloc(64);\n"
" int x = p[0];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: p\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar("void f()\n"
"{\n" "{\n"
" Fred *fred = new Fred;\n" " Fred *fred = new Fred;\n"