Fixed #2954 (False negative: Null pointer dereference not detected '*p=4; if (p) { }')

This commit is contained in:
Daniel Marjamäki 2011-08-02 11:20:09 +02:00
parent 5fc2a55bac
commit 825dce5c4e
2 changed files with 22 additions and 15 deletions

View File

@ -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")

View File

@ -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"