Fixed #440 (NULL referencing not detected)

This commit is contained in:
Daniel Marjamäki 2010-01-03 13:30:20 +01:00
parent e1ed22aa2b
commit fa535ff3ae
3 changed files with 101 additions and 2 deletions

View File

@ -1252,6 +1252,29 @@ private:
return vartok->next();
}
// Template pointer variable..
if (Token::Match(tok.previous(), "[;{}] %type% ::|<"))
{
const Token * vartok = &tok;
while (Token::Match(vartok, "%type% ::"))
vartok = vartok->tokAt(2);
if (Token::Match(vartok, "%type% < %type%"))
{
vartok = vartok->tokAt(3);
while (vartok && (vartok->str() == "*" || vartok->isName()))
vartok = vartok->next();
if (Token::Match(vartok, "> * %var% ;|="))
{
vartok = vartok->tokAt(2);
checks.push_back(new CheckNullpointer(owner, vartok->varId(), vartok->str()));
if (Token::simpleMatch(vartok->next(), "= 0 ;"))
setnull(checks, vartok->varId());
return vartok->next();
}
}
}
if (Token::Match(&tok, "%var% ("))
{
// parse usage..
@ -1554,6 +1577,25 @@ private:
declare(checks, vartok, tok, false, true);
return vartok->next()->link()->next();
}
// Template pointer variable..
if (Token::Match(tok.previous(), "[;{}] %type% ::|<"))
{
const Token * vartok = &tok;
while (Token::Match(vartok, "%type% ::"))
vartok = vartok->tokAt(2);
if (Token::Match(vartok, "%type% < %type%"))
{
vartok = vartok->tokAt(3);
while (vartok && (vartok->str() == "*" || vartok->isName()))
vartok = vartok->next();
if (Token::Match(vartok, "> * %var% ;"))
{
declare(checks, vartok->tokAt(2), tok, true, false);
return vartok->tokAt(2);
}
}
}
}
if (tok.varId())
@ -1646,6 +1688,7 @@ private:
// is the variable passed as a parameter to some function?
unsigned int parlevel = 0;
std::set<unsigned int> bailouts;
for (const Token *tok2 = tok.next(); tok2; tok2 = tok2->next())
{
if (tok2->str() == "(")
@ -1667,13 +1710,16 @@ private:
else if (tok2->varId())
{
if (Token::Match(tok2->tokAt(-2), "[(,] *"))
if (Token::Match(tok2->tokAt(-2), "[(,] *") || Token::Match(tok2->next(), ". %var%"))
use_dead_pointer(foundError, checks, tok2);
// it is possible that the variable is initialized here
ExecutionPath::bailOutVar(checks, tok2->varId());
bailouts.insert(tok2->varId());
}
}
for (std::set<unsigned int>::const_iterator it = bailouts.begin(); it != bailouts.end(); ++it)
ExecutionPath::bailOutVar(checks, *it);
}
// function call via function pointer

View File

@ -65,6 +65,29 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
if (tok->str() == "}")
return 0;
if (Token::simpleMatch(tok, "while ("))
{
// parse condition
if (checks.size() > 10 || check->parseCondition(*tok->tokAt(2), checks))
{
ExecutionPath::bailOut(checks);
return 0;
}
// skip "while (fgets()!=NULL)"
if (Token::simpleMatch(tok, "while ( fgets ("))
{
const Token *tok2 = tok->tokAt(3)->link();
if (Token::simpleMatch(tok2, ") ) {"))
{
tok = tok2->tokAt(2)->link();
if (!tok)
break;
continue;
}
}
}
// todo: handle for/while
if (Token::Match(tok, "for|while|switch|do"))
{

View File

@ -929,6 +929,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str());
checkNullPointer("static void foo(int x)\n"
"{\n"
" Foo<int> *abc = 0;\n"
" abc->a();\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc\n", errout.str());
// no false positive..
checkNullPointer("static void foo()\n"
"{\n"
@ -992,6 +999,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
checkUninitVar("static void foo()\n"
"{\n"
" Foo<int> *p;\n"
" p->abcd();\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
checkUninitVar("static void foo()\n"
"{\n"
" int *p;\n"
@ -1308,6 +1322,15 @@ private:
"}\n");
ASSERT_EQUALS("", errout.str());
// while..
checkUninitVar("int f()\n"
"{\n"
" int i;\n"
" while (fgets())\n"
" i = 1;\n"
" return i;"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: i\n", errout.str());
// member variables..
checkUninitVar("class Fred\n"
@ -1365,6 +1388,13 @@ private:
"}\n");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void foo()\n"
"{\n"
" Foo *p;\n"
" x = bar(p->begin());\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
// arrays..
checkUninitVar("void f()\n"
"{\n"