Fixed #6014: Added plausibility check before issuing null pointer messages on function calls defined in library

This commit is contained in:
PKEuS 2015-01-02 13:35:39 +01:00
parent 88990bac59
commit c4fd8919a2
2 changed files with 40 additions and 4 deletions

View File

@ -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 * @brief parse a function call and extract information about variable usage
* @param tok first token * @param tok first token
@ -52,7 +57,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
(value == 0 && Token::Match(firstParam, "0|NULL ,|)"))) { (value == 0 && Token::Match(firstParam, "0|NULL ,|)"))) {
if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero
var.push_back(firstParam); 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); 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); var.push_back(firstParam);
@ -60,7 +65,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
// 2nd parameter.. // 2nd parameter..
if ((value == 0 && Token::Match(secondParam, "0|NULL ,|)")) || (secondParam && secondParam->varId() > 0 && Token::Match(secondParam->next(),"[,)]"))) { 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); 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); var.push_back(secondParam);

View File

@ -59,6 +59,7 @@ private:
TEST_CASE(nullpointer24); // #5082 fp: chained assignment TEST_CASE(nullpointer24); // #5082 fp: chained assignment
TEST_CASE(nullpointer25); // #5061 TEST_CASE(nullpointer25); // #5061
TEST_CASE(nullpointer26); // #3589 TEST_CASE(nullpointer26); // #3589
TEST_CASE(nullpointer27); // #6014
TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointerSwitch); // #2626
TEST_CASE(nullpointer_cast); // #4692 TEST_CASE(nullpointer_cast); // #4692
TEST_CASE(nullpointer_castToVoid); // #3771 TEST_CASE(nullpointer_castToVoid); // #3771
@ -1304,6 +1305,36 @@ private:
ASSERT_EQUALS("", errout.str()); 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 void nullpointerSwitch() { // #2626
check("char *f(int x) {\n" check("char *f(int x) {\n"
" char *p = do_something();\n" " char *p = do_something();\n"