Fixed #2954 (False negative: Null pointer dereference not detected '*p=4; if (p) { }')
This commit is contained in:
parent
5fc2a55bac
commit
825dce5c4e
|
@ -513,15 +513,19 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
// TODO: false negatives.
|
// TODO: false negatives.
|
||||||
// - logical operators
|
// - logical operators
|
||||||
// - while
|
// - while
|
||||||
if (tok->str() == "if" && Token::Match(tok->previous(), "; if ( ! %var% )"))
|
if (tok->str() == "if" && Token::Match(tok->previous(), "; if ( !| %var% )"))
|
||||||
{
|
{
|
||||||
|
const Token * vartok = tok->tokAt(2);
|
||||||
|
if (vartok->str() == "!")
|
||||||
|
vartok = vartok->next();
|
||||||
|
|
||||||
// Variable id for pointer
|
// Variable id for pointer
|
||||||
const unsigned int varid(tok->tokAt(3)->varId());
|
const unsigned int varid(vartok->varId());
|
||||||
if (varid == 0)
|
if (varid == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Name of pointer
|
// Name of pointer
|
||||||
const std::string varname(tok->strAt(3));
|
const std::string varname(vartok->str());
|
||||||
|
|
||||||
// Check that variable is a pointer..
|
// Check that variable is a pointer..
|
||||||
if (!isPointer(varid))
|
if (!isPointer(varid))
|
||||||
|
@ -535,8 +539,10 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
if (tok1->str() == ")" && Token::Match(tok1->link()->previous(), "%var% ("))
|
if (tok1->str() == ")" && Token::Match(tok1->link()->previous(), "%var% ("))
|
||||||
{
|
{
|
||||||
const Token *tok2 = tok1->link();
|
const Token *tok2 = tok1->link();
|
||||||
while (tok2 && !Token::Match(tok2, "[;{}]"))
|
while (tok2 && !Token::Match(tok2, "[;{}?:]"))
|
||||||
tok2 = tok2->previous();
|
tok2 = tok2->previous();
|
||||||
|
if (Token::Match(tok2, "[?:]"))
|
||||||
|
break;
|
||||||
if (Token::Match(tok2, "[;{}] %varid% = %var%", varid))
|
if (Token::Match(tok2, "[;{}] %varid% = %var%", varid))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -559,6 +565,11 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calling unknown function => it might initialize the pointer
|
||||||
|
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||||
|
if (!var || !(var->isLocal() || var->isArgument()))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok1->str() == "break")
|
if (tok1->str() == "break")
|
||||||
|
|
|
@ -306,17 +306,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// loops..
|
// loops..
|
||||||
check("void freeAbc(struct ABC *abc)\n"
|
|
||||||
"{\n"
|
|
||||||
" while (abc)\n"
|
|
||||||
" {\n"
|
|
||||||
" struct ABC *next = abc->next;\n"
|
|
||||||
" if (abc) delete abc;\n"
|
|
||||||
" abc = next;\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void foo(struct ABC *abc)\n"
|
check("void foo(struct ABC *abc)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a = abc->a;"
|
" int a = abc->a;"
|
||||||
|
@ -410,6 +399,13 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 4\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 4\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(int *p)\n"
|
||||||
|
"{\n"
|
||||||
|
" *p = 0;\n"
|
||||||
|
" if (p) { }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 4\n", errout.str());
|
||||||
|
|
||||||
check("void foo(int *p)\n"
|
check("void foo(int *p)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" bar(*p);\n"
|
" bar(*p);\n"
|
||||||
|
|
Loading…
Reference in New Issue