Fixed #2127 (null pointer dereference after condition (SRD nr 522))
This commit is contained in:
parent
41a06a21d9
commit
026514db1a
|
@ -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) */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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..
|
||||||
|
|
Loading…
Reference in New Issue