Null pointers: show inconclusive errors if functions are called. Assume they won't assign the pointer. Ticket: #3443
This commit is contained in:
parent
293437bdfc
commit
385afffb14
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue