Fixed #6014: Added plausibility check before issuing null pointer messages on function calls defined in library
This commit is contained in:
parent
88990bac59
commit
c4fd8919a2
|
@ -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::list<const Token
|
|||
(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
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue