Improved parsing of functions that accept nullpointers but no uninitialized data (Fixed #3811)
This commit is contained in:
parent
132a95b5f2
commit
e8cd119ebd
|
@ -55,6 +55,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
// standard functions that dereference first parameter..
|
// standard functions that dereference first parameter..
|
||||||
static std::set<std::string> functionNames1_all;
|
static std::set<std::string> functionNames1_all;
|
||||||
static std::set<std::string> functionNames1_nullptr;
|
static std::set<std::string> functionNames1_nullptr;
|
||||||
|
static std::set<std::string> functionNames1_uninit;
|
||||||
if (functionNames1_all.empty()) {
|
if (functionNames1_all.empty()) {
|
||||||
// cstdlib
|
// cstdlib
|
||||||
functionNames1_all.insert("atoi");
|
functionNames1_all.insert("atoi");
|
||||||
|
@ -106,7 +107,6 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
functionNames1_all.insert("rename");
|
functionNames1_all.insert("rename");
|
||||||
functionNames1_all.insert("remove");
|
functionNames1_all.insert("remove");
|
||||||
functionNames1_all.insert("puts");
|
functionNames1_all.insert("puts");
|
||||||
functionNames1_all.insert("perror");
|
|
||||||
functionNames1_all.insert("getc");
|
functionNames1_all.insert("getc");
|
||||||
functionNames1_all.insert("clearerr");
|
functionNames1_all.insert("clearerr");
|
||||||
// ctime
|
// ctime
|
||||||
|
@ -132,6 +132,9 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
functionNames1_nullptr.insert("gmtime");
|
functionNames1_nullptr.insert("gmtime");
|
||||||
functionNames1_nullptr.insert("localtime");
|
functionNames1_nullptr.insert("localtime");
|
||||||
functionNames1_nullptr.insert("strftime");
|
functionNames1_nullptr.insert("strftime");
|
||||||
|
|
||||||
|
functionNames1_uninit.insert("perror");
|
||||||
|
functionNames1_uninit.insert("fflush");
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard functions that dereference second parameter..
|
// standard functions that dereference second parameter..
|
||||||
|
@ -184,7 +187,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
||||||
var.push_back(firstParam);
|
var.push_back(firstParam);
|
||||||
else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
|
else if (value == 0 && functionNames1_nullptr.find(tok.str()) != functionNames1_nullptr.end())
|
||||||
var.push_back(firstParam);
|
var.push_back(firstParam);
|
||||||
else if (value != 0 && tok.str() == "fflush")
|
else if (value != 0 && functionNames1_uninit.find(tok.str()) != functionNames1_uninit.end())
|
||||||
var.push_back(firstParam);
|
var.push_back(firstParam);
|
||||||
else if (value == 0 && Token::Match(&tok, "snprintf|vsnprintf|fnprintf|vfnprintf") && secondParam && secondParam->str() != "0") // Only if length (second parameter) is not zero
|
else 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);
|
||||||
|
|
|
@ -52,6 +52,7 @@ private:
|
||||||
TEST_CASE(nullpointer16); // #3591
|
TEST_CASE(nullpointer16); // #3591
|
||||||
TEST_CASE(nullpointer17); // #3567
|
TEST_CASE(nullpointer17); // #3567
|
||||||
TEST_CASE(nullpointer18); // #1927
|
TEST_CASE(nullpointer18); // #1927
|
||||||
|
TEST_CASE(nullpointer19); // #3811
|
||||||
TEST_CASE(nullpointer_castToVoid); // #3771
|
TEST_CASE(nullpointer_castToVoid); // #3771
|
||||||
TEST_CASE(pointerCheckAndDeRef); // check if pointer is null and then dereference it
|
TEST_CASE(pointerCheckAndDeRef); // check if pointer is null and then dereference it
|
||||||
TEST_CASE(nullConstantDereference); // Dereference NULL constant
|
TEST_CASE(nullConstantDereference); // Dereference NULL constant
|
||||||
|
@ -1250,6 +1251,13 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nullpointer19() { // #3811
|
||||||
|
check("int foo() {\n"
|
||||||
|
" perror(0);\n"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void nullpointer_castToVoid() { // #3771
|
void nullpointer_castToVoid() { // #3771
|
||||||
check("void f () {\n"
|
check("void f () {\n"
|
||||||
" int *buf = NULL;\n"
|
" int *buf = NULL;\n"
|
||||||
|
|
|
@ -1193,6 +1193,13 @@ private:
|
||||||
"};\n");
|
"};\n");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s\n", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" char *s = malloc(100);\n"
|
||||||
|
" perror(s);\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Data is allocated but not initialized: s\n", errout.str());
|
||||||
|
|
||||||
checkUninitVar("void f()\n"
|
checkUninitVar("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *s1 = new char[10];\n"
|
" char *s1 = new char[10];\n"
|
||||||
|
|
Loading…
Reference in New Issue