Fix 10640: FN nullPointerRedundantCheck (#3607)
* Fix 10640: FN nullPointerRedundantCheck * Format
This commit is contained in:
parent
d2926bfa96
commit
0be6e27231
|
@ -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% ) (") &&
|
||||||
|
|
|
@ -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(), ") {"))
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue