Fix 10640: FN nullPointerRedundantCheck (#3607)

* Fix 10640: FN nullPointerRedundantCheck

* Format
This commit is contained in:
Paul Fultz II 2021-12-06 13:06:48 -06:00 committed by GitHub
parent d2926bfa96
commit 0be6e27231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 15 deletions

View File

@ -168,7 +168,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set
const Token* parent = tok->astParent(); const Token* parent = tok->astParent();
if (!parent) if (!parent)
return false; return false;
if (parent->str() == "." && parent->astOperand2() == tok) const bool addressOf = parent->astParent() && parent->astParent()->str() == "&";
if (parent->str() == "." && astIsRHS(tok))
return isPointerDeRef(parent, unknown, settings); return isPointerDeRef(parent, unknown, settings);
const bool firstOperand = parent->astOperand1() == tok; const bool firstOperand = parent->astOperand1() == tok;
parent = astParentSkipParens(tok); parent = astParentSkipParens(tok);
@ -176,11 +177,11 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set
return false; return false;
// Dereferencing pointer.. // Dereferencing pointer..
if (parent->isUnaryOp("*") && !Token::Match(parent->tokAt(-2), "sizeof|decltype|typeof")) if (parent->isUnaryOp("*") && !addressOf)
return true; return true;
// array access // array access
if (firstOperand && parent->str() == "[" && (!parent->astParent() || parent->astParent()->str() != "&")) if (firstOperand && parent->str() == "[" && !addressOf)
return true; return true;
// address of member variable / array element // address of member variable / array element
@ -191,18 +192,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set
return false; return false;
// read/write member variable // read/write member variable
if (firstOperand && parent->originalName() == "->" && (!parent->astParent() || parent->astParent()->str() != "&")) { if (firstOperand && parent->originalName() == "->" && !addressOf)
if (!parent->astParent()) return true;
return true;
if (!Token::Match(parent->astParent()->previous(), "if|while|for|switch ("))
return true;
if (!Token::Match(parent->astParent()->previous(), "%name% ("))
return true;
if (parent->astParent() == tok->previous())
return true;
unknown = true;
return false;
}
// If its a function pointer then check if its called // If its a function pointer then check if its called
if (tok->variable() && tok->variable()->isPointer() && Token::Match(tok->variable()->nameToken(), "%name% ) (") && if (tok->variable() && tok->variable()->isPointer() && Token::Match(tok->variable()->nameToken(), "%name% ) (") &&

View File

@ -302,6 +302,12 @@ struct ReverseTraversal {
if (action.isModified()) if (action.isModified())
break; break;
} }
Token* condTok = getCondTokFromEnd(tok->link());
if (condTok) {
Analyzer::Result r = valueFlowGenericForward(condTok, analyzer, settings);
if (r.action.isModified())
break;
}
if (Token::simpleMatch(tok->tokAt(-2), "} else {")) if (Token::simpleMatch(tok->tokAt(-2), "} else {"))
tok = tok->linkAt(-2); tok = tok->linkAt(-2);
if (Token::simpleMatch(tok->previous(), ") {")) if (Token::simpleMatch(tok->previous(), ") {"))

View File

@ -128,6 +128,7 @@ private:
TEST_CASE(nullpointer86); TEST_CASE(nullpointer86);
TEST_CASE(nullpointer87); // #9291 TEST_CASE(nullpointer87); // #9291
TEST_CASE(nullpointer88); // #9949 TEST_CASE(nullpointer88); // #9949
TEST_CASE(nullpointer89); // #10640
TEST_CASE(nullpointer_addressOf); // address of TEST_CASE(nullpointer_addressOf); // address of
TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointerSwitch); // #2626
TEST_CASE(nullpointer_cast); // #4692 TEST_CASE(nullpointer_cast); // #4692
@ -2618,6 +2619,23 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void nullpointer89() // #10640
{
check("typedef struct {\n"
" int x;\n"
"} foo_t;\n"
"typedef struct {\n"
" foo_t *y;\n"
"} bar_t;\n"
"void f(bar_t *ptr) {\n"
" if(ptr->y->x)\n"
" if(ptr->y != nullptr) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:9] -> [test.cpp:8]: (warning) Either the condition 'ptr->y!=nullptr' is redundant or there is possible null pointer dereference: ptr->y.\n",
errout.str());
}
void nullpointer_addressOf() { // address of void nullpointer_addressOf() { // address of
check("void f() {\n" check("void f() {\n"
" struct X *x = 0;\n" " struct X *x = 0;\n"