Fixed #2127 (null pointer dereference after condition (SRD nr 522))

This commit is contained in:
Daniel Marjamäki 2010-10-25 19:43:54 +02:00
parent 41a06a21d9
commit 026514db1a
3 changed files with 93 additions and 0 deletions

View File

@ -2534,6 +2534,69 @@ void CheckOther::nullPointerByDeRefAndChec()
} }
} }
void CheckOther::nullPointerByCheckAndDeRef()
{
// Check if pointer is NULL and then dereference it..
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "if ( ! %var% ) {"))
{
bool null = true;
const unsigned int varid(tok->tokAt(3)->varId());
unsigned int indentlevel = 1;
for (const Token *tok2 = tok->tokAt(6); tok2; tok2 = tok2->next())
{
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}")
{
if (indentlevel == 0)
break;
--indentlevel;
if (null && indentlevel == 0)
{
// skip all "else" blocks because they are not executed in this execution path
while (Token::Match(tok2, "} else {"))
tok2 = tok2->tokAt(2)->link();
null = false;
}
}
if (Token::Match(tok2, "goto|return|continue|break|if"))
{
if (Token::Match(tok2, "return * %var%"))
nullPointerError(tok2, tok->strAt(3));
break;
}
if (tok2->varId() == varid)
{
if (Token::Match(tok2->previous(), "[;{}=] %var% = 0 ;"))
;
else if (Token::Match(tok2->tokAt(-2), "[;{}=+-/(,] * %var%"))
nullPointerError(tok2, tok->strAt(3));
else if (!Token::simpleMatch(tok2->tokAt(-2), "& (") && Token::Match(tok2->next(), ". %var%"))
nullPointerError(tok2, tok->strAt(3));
else if (Token::Match(tok2->previous(), "[;{}=+-/(,] %var% [ %any% ]"))
nullPointerError(tok2, tok->strAt(3));
else if (Token::Match(tok2->previous(), "return %var% [ %any% ]"))
nullPointerError(tok2, tok->strAt(3));
else if (Token::Match(tok2, "%var% ("))
nullPointerError(tok2, tok->strAt(3));
else
break;
}
}
}
}
}
void CheckOther::nullPointer() void CheckOther::nullPointer()
{ {
@ -2541,6 +2604,7 @@ void CheckOther::nullPointer()
nullPointerLinkedList(); nullPointerLinkedList();
nullPointerStructByDeRefAndChec(); nullPointerStructByDeRefAndChec();
nullPointerByDeRefAndChec(); nullPointerByDeRefAndChec();
nullPointerByCheckAndDeRef();
} }
/** Derefencing null constant (simplified token list) */ /** Derefencing null constant (simplified token list) */

View File

@ -89,6 +89,9 @@ public:
// New type of check: Check execution paths // New type of check: Check execution paths
checkOther.executionPaths(); checkOther.executionPaths();
checkOther.checkMisusedScopedObject(); checkOther.checkMisusedScopedObject();
// FIXME: I get a deadlock if I uncomment this:
//nullPointerByCheckAndDeRef();
} }
@ -324,6 +327,12 @@ private:
*/ */
void nullPointerByDeRefAndChec(); void nullPointerByDeRefAndChec();
/**
* @brief Does one part of the check for nullPointer().
* Checking if pointer is NULL and then dereferencing it..
*/
void nullPointerByCheckAndDeRef();
/** /**
* @brief Does one part of the check for nullPointer(). * @brief Does one part of the check for nullPointer().
* -# initialize pointer to 0 * -# initialize pointer to 0

View File

@ -68,6 +68,7 @@ private:
TEST_CASE(nullpointer7); TEST_CASE(nullpointer7);
TEST_CASE(nullpointer8); TEST_CASE(nullpointer8);
TEST_CASE(nullpointer9); TEST_CASE(nullpointer9);
TEST_CASE(nullpointer10); // check if pointer is null and then dereference it
TEST_CASE(uninitvar1); TEST_CASE(uninitvar1);
TEST_CASE(uninitvar_alloc); // data is allocated but not initialized TEST_CASE(uninitvar_alloc); // data is allocated but not initialized
@ -1148,6 +1149,25 @@ private:
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: x\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: x\n", errout.str());
} }
// Check if pointer is null and the dereference it
void nullpointer10()
{
checkNullPointer("void foo(char *p) {\n"
" if (!p) {\n"
" }\n"
" *p = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str());
checkNullPointer("void foo(abc *p) {\n"
" if (!p) {\n"
" }\n"
" else if (!p->x) {\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void checkUninitVar(const char code[]) void checkUninitVar(const char code[])
{ {
// Tokenize.. // Tokenize..