From c4fd8919a2db8e4031d66a40680afc619e5b85d5 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Fri, 2 Jan 2015 13:35:39 +0100 Subject: [PATCH] Fixed #6014: Added plausibility check before issuing null pointer messages on function calls defined in library --- lib/checknullpointer.cpp | 13 +++++++++---- test/testnullpointer.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 4d1527ccb..ab89e8fab 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -31,6 +31,11 @@ namespace { //--------------------------------------------------------------------------- +static bool checkNullpointerFunctionCallPlausibility(const Function* func, unsigned int arg) +{ + return !func || (func->argCount() >= arg && func->getArgumentVar(arg - 1) && func->getArgumentVar(arg - 1)->isPointer()); +} + /** * @brief parse a function call and extract information about variable usage * @param tok first token @@ -52,17 +57,17 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::liststr() != "0") // Only if length (second parameter) is not zero var.push_back(firstParam); - else if (value == 0 && library != nullptr && library->isnullargbad(tok.str(),1)) + else if (value == 0 && library != nullptr && library->isnullargbad(tok.str(), 1) && checkNullpointerFunctionCallPlausibility(tok.function(), 1)) var.push_back(firstParam); - else if (value == 1 && library != nullptr && library->isuninitargbad(tok.str(),1)) + else if (value == 1 && library != nullptr && library->isuninitargbad(tok.str(), 1)) var.push_back(firstParam); } // 2nd parameter.. if ((value == 0 && Token::Match(secondParam, "0|NULL ,|)")) || (secondParam && secondParam->varId() > 0 && Token::Match(secondParam->next(),"[,)]"))) { - if (value == 0 && library != nullptr && library->isnullargbad(tok.str(),2)) + if (value == 0 && library != nullptr && library->isnullargbad(tok.str(), 2) && checkNullpointerFunctionCallPlausibility(tok.function(), 2)) var.push_back(secondParam); - else if (value == 1 && library != nullptr && library->isuninitargbad(tok.str(),2)) + else if (value == 1 && library != nullptr && library->isuninitargbad(tok.str(), 2)) var.push_back(secondParam); } diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index d9e156314..6341d2e80 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -59,6 +59,7 @@ private: TEST_CASE(nullpointer24); // #5082 fp: chained assignment TEST_CASE(nullpointer25); // #5061 TEST_CASE(nullpointer26); // #3589 + TEST_CASE(nullpointer27); // #6014 TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointer_cast); // #4692 TEST_CASE(nullpointer_castToVoid); // #3771 @@ -1304,6 +1305,36 @@ private: ASSERT_EQUALS("", errout.str()); } + void nullpointer27() { // #6014 + check("void fgetpos(int x, int y);\n" + "void foo() {\n" + " fgetpos(0, x);\n" + " fgetpos(x, 0);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void fgetpos(void* x, int y);\n" + "void foo() {\n" + " fgetpos(0, x);\n" + " fgetpos(x, 0);\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n", errout.str()); + + check("void fgetpos(int x, void* y);\n" + "void foo() {\n" + " fgetpos(0, x);\n" + " fgetpos(x, 0);\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); + + check("void foo() {\n" + " fgetpos(0, x);\n" + " fgetpos(x, 0);\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n" + "[test.cpp:3]: (error) Null pointer dereference\n", errout.str()); + } + void nullpointerSwitch() { // #2626 check("char *f(int x) {\n" " char *p = do_something();\n"