Null pointers: show inconclusive errors if functions are called. Assume they won't assign the pointer. Ticket: #3443

This commit is contained in:
Daniel Marjamäki 2011-12-26 07:13:10 +01:00
parent 293437bdfc
commit 385afffb14
3 changed files with 31 additions and 8 deletions

View File

@ -623,8 +623,11 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
break; break;
// function call.. // function call..
else if (Token::Match(tok2, "[;{}] %var% (") && CanFunctionAssignPointer(tok2->next(), varid1)) else if (Token::Match(tok2, "[;{}] %var% (") && CanFunctionAssignPointer(tok2->next(), varid1)) {
break; if (!_settings->inconclusive)
break;
inconclusive = true;
}
// Reassignment of the struct // Reassignment of the struct
else if (tok2->varId() == varid1) { else if (tok2->varId() == varid1) {
@ -698,6 +701,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
continue; continue;
const Token * const decltok = var->nameToken(); const Token * const decltok = var->nameToken();
bool inconclusive = false;
for (const Token *tok1 = tok->previous(); tok1 && tok1 != decltok; tok1 = tok1->previous()) { for (const Token *tok1 = tok->previous(); tok1 && tok1 != decltok; tok1 = tok1->previous()) {
if (tok1->str() == ")" && Token::Match(tok1->link()->previous(), "%var% (")) { if (tok1->str() == ")" && Token::Match(tok1->link()->previous(), "%var% (")) {
@ -727,15 +731,18 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
std::list<const Token *> varlist; std::list<const Token *> varlist;
parseFunctionCall(*(tok2->next()), varlist, 0); parseFunctionCall(*(tok2->next()), varlist, 0);
if (!varlist.empty() && varlist.front() == tok2->tokAt(3)) { if (!varlist.empty() && varlist.front() == tok2->tokAt(3)) {
nullPointerError(tok2->tokAt(3), varname, tok->linenr()); nullPointerError(tok2->tokAt(3), varname, tok->linenr(), inconclusive);
break; break;
} }
} }
// Passing pointer as parameter.. // Passing pointer as parameter..
if (Token::Match(tok2, "[;{}] %type% (")) { if (Token::Match(tok2, "[;{}] %type% (")) {
if (CanFunctionAssignPointer(tok2->next(), varid)) if (CanFunctionAssignPointer(tok2->next(), varid)) {
break; if (!_settings->inconclusive)
break;
inconclusive = true;
}
} }
// calling unknown function => it might initialize the pointer // calling unknown function => it might initialize the pointer
@ -780,7 +787,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
} else if (Token::Match(tok1->tokAt(-2), "&&|%oror% !")) { } else if (Token::Match(tok1->tokAt(-2), "&&|%oror% !")) {
break; break;
} else if (CheckNullPointer::isPointerDeRef(tok1, unknown)) { } else if (CheckNullPointer::isPointerDeRef(tok1, unknown)) {
nullPointerError(tok1, varname, tok->linenr()); nullPointerError(tok1, varname, tok->linenr(), inconclusive);
break; break;
} else if (Token::simpleMatch(tok1->previous(), "&")) { } else if (Token::simpleMatch(tok1->previous(), "&")) {
break; break;

View File

@ -504,8 +504,8 @@ public:
* @param expandedtemplates all templates that has been expanded so far. The full names are stored. * @param expandedtemplates all templates that has been expanded so far. The full names are stored.
*/ */
void simplifyTemplateInstantions(const Token *tok, void simplifyTemplateInstantions(const Token *tok,
std::list<Token *> &templateInstantiations, std::list<Token *> &templateInstantiations,
std::set<std::string> &expandedtemplates); std::set<std::string> &expandedtemplates);
void simplifyTemplatesExpandTemplate(const Token *tok, void simplifyTemplatesExpandTemplate(const Token *tok,
const std::string &name, const std::string &name,

View File

@ -1749,6 +1749,14 @@ private:
" if (p) { }\n" " if (p) { }\n"
"}"); "}");
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 6\n", "", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 6\n", "", errout.str());
// inconclusive
check("void f(int *p) {\n"
" *p = 0;\n"
" foo(p);\n"
" if (p) { }\n"
"}", true);
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: p - otherwise it is redundant to check if p is null at line 4\n", errout.str());
} }
// dereference struct pointer and then check if it's null // dereference struct pointer and then check if it's null
@ -1780,6 +1788,14 @@ private:
" if (abc) { }\n" " if (abc) { }\n"
"}"); "}");
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 6\n", "", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 6\n", "", errout.str());
// inconclusive
check("void f(struct ABC *abc) {\n"
" abc->a = 0;\n"
" foo(abc);\n"
" if (abc) { }\n"
"}", true);
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: abc - otherwise it is redundant to check if abc is null at line 4\n", errout.str());
} }
} }
}; };