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
|
* @brief parse a function call and extract information about variable usage
|
||||||
* @param tok first token
|
* @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 ,|)"))) {
|
(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue