Better distinguishing between possible and known null pointer dereferenciations (#7157)

This commit is contained in:
PKEuS 2016-01-30 20:43:21 +01:00
parent 11be3a9265
commit 923f7f843d
3 changed files with 42 additions and 44 deletions

View File

@ -291,7 +291,7 @@ void CheckNullPointer::nullPointerLinkedList()
// for statement. // for statement.
for (const Token *tok4 = scope->classStart; tok4; tok4 = tok4->next()) { for (const Token *tok4 = scope->classStart; tok4; tok4 = tok4->next()) {
if (tok4 == i->classEnd) { if (tok4 == i->classEnd) {
nullPointerError(tok1, var->name(), scope->classDef); nullPointerError(tok1, var->name(), scope->classDef, false);
break; break;
} }
@ -345,7 +345,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
parseFunctionCall(*ftok->previous(), varlist, &_settings->library, 0); parseFunctionCall(*ftok->previous(), varlist, &_settings->library, 0);
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) { if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
if (value->condition == nullptr) if (value->condition == nullptr)
nullPointerError(tok, tok->str(), false, value->defaultArg); nullPointerError(tok, tok->str(), false, value->defaultArg, !value->isKnown());
else if (printWarnings) else if (printWarnings)
nullPointerError(tok, tok->str(), value->condition, value->inconclusive); nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
} }
@ -357,7 +357,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
if (!isPointerDeRef(tok,unknown)) { if (!isPointerDeRef(tok,unknown)) {
if (printInconclusive && unknown) { if (printInconclusive && unknown) {
if (value->condition == nullptr) if (value->condition == nullptr)
nullPointerError(tok, tok->str(), true, value->defaultArg); nullPointerError(tok, tok->str(), true, value->defaultArg, !value->isKnown());
else else
nullPointerError(tok, tok->str(), value->condition, true); nullPointerError(tok, tok->str(), value->condition, true);
} }
@ -365,7 +365,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
} }
if (value->condition == nullptr) if (value->condition == nullptr)
nullPointerError(tok, tok->str(), value->inconclusive, value->defaultArg); nullPointerError(tok, tok->str(), value->inconclusive, value->defaultArg, !value->isKnown());
else if (printWarnings) else if (printWarnings)
nullPointerError(tok, tok->str(), value->condition, value->inconclusive); nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
} }
@ -471,13 +471,16 @@ void CheckNullPointer::nullPointerError(const Token *tok)
reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false); reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false);
} }
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg) void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible)
{ {
if (defaultArg) { if (defaultArg) {
if (_settings->isEnabled("warning")) if (_settings->isEnabled("warning"))
reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, CWE(0U), inconclusive); reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, CWE(0U), inconclusive);
} else if (possible) {
if (_settings->isEnabled("warning"))
reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference: " + varname, CWE476, inconclusive);
} else } else
reportError(tok, Severity::error, "nullPointer", "Possible null pointer dereference: " + varname, CWE476, inconclusive); reportError(tok, Severity::error, "nullPointer", "Null pointer dereference: " + varname, CWE476, inconclusive);
} }
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive) void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive)

View File

@ -86,16 +86,16 @@ public:
void nullConstantDereference(); void nullConstantDereference();
void nullPointerError(const Token *tok); // variable name unknown / doesn't exist void nullPointerError(const Token *tok); // variable name unknown / doesn't exist
void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive = false, bool defaultArg = false); void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible);
void nullPointerError(const Token *tok, const std::string &varname, const Token* nullcheck, bool inconclusive = false); void nullPointerError(const Token *tok, const std::string &varname, const Token* nullcheck, bool inconclusive);
private: private:
/** Get error messages. Used by --errorlist */ /** Get error messages. Used by --errorlist */
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckNullPointer c(0, settings, errorLogger); CheckNullPointer c(0, settings, errorLogger);
c.nullPointerError(0); c.nullPointerError(0);
c.nullPointerError(0, "pointer", false, true); c.nullPointerError(0, "pointer", false, true, true);
c.nullPointerError(0, "pointer", nullptr); c.nullPointerError(0, "pointer", nullptr, false);
} }
/** Name of check */ /** Name of check */

View File

@ -892,7 +892,7 @@ private:
// inconclusive=true => error // inconclusive=true => error
check(code, true); check(code, true);
ASSERT_EQUALS("[test.cpp:3]: (error, inconclusive) Possible null pointer dereference: abc\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error, inconclusive) Null pointer dereference: abc\n", errout.str());
} }
check("static void foo() {\n" check("static void foo() {\n"
@ -908,7 +908,7 @@ private:
" }\n" " }\n"
" c[0] = 0;\n" " c[0] = 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:7]: (error) Possible null pointer dereference: c\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Null pointer dereference: c\n", errout.str());
check("static void foo() {\n" check("static void foo() {\n"
" if (3 > *0);\n" " if (3 > *0);\n"
@ -970,7 +970,7 @@ private:
" *Q=1;\n" " *Q=1;\n"
" return Q;\n" " return Q;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:12]: (error) Possible null pointer dereference: Q\n", errout.str()); ASSERT_EQUALS("[test.cpp:12]: (warning) Possible null pointer dereference: Q\n", errout.str());
// Ticket #2052 (false positive for 'else continue;') // Ticket #2052 (false positive for 'else continue;')
check("void f() {\n" check("void f() {\n"
@ -990,7 +990,7 @@ private:
" f = 0;\n" " f = 0;\n"
" f();\n" " f();\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Possible null pointer dereference: f\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference: f\n", errout.str());
// loops.. // loops..
check("void f() {\n" check("void f() {\n"
@ -999,7 +999,7 @@ private:
" int x = *p + 1;\n" " int x = *p + 1;\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: p\n", errout.str());
check("void f(int a) {\n" check("void f(int a) {\n"
" const char *p = 0;\n" " const char *p = 0;\n"
@ -1098,7 +1098,7 @@ private:
"\n" "\n"
" *p = 0;\n" " *p = 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:11]: (error) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:11]: (warning) Possible null pointer dereference: p\n", errout.str());
} }
void nullpointer7() { void nullpointer7() {
@ -1116,8 +1116,7 @@ private:
" std::string * x = 0;\n" " std::string * x = 0;\n"
" *x = \"test\";\n" " *x = \"test\";\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: x\n" ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: x\n", errout.str());
"[test.cpp:4]: (error) Null pointer dereference\n", errout.str());
} }
void nullpointer10() { void nullpointer10() {
@ -1126,7 +1125,7 @@ private:
" struct my_type* p = 0;\n" " struct my_type* p = 0;\n"
" p->x = 0;\n" " p->x = 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: p\n", errout.str());
} }
void nullpointer11() { // ticket #2812 void nullpointer11() { // ticket #2812
@ -1136,7 +1135,7 @@ private:
" p = 0;\n" " p = 0;\n"
" return p->x;\n" " return p->x;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference: p\n", errout.str());
} }
void nullpointer12() { // ticket #2470, #4035 void nullpointer12() { // ticket #2470, #4035
@ -1147,8 +1146,7 @@ private:
"}\n"; "}\n";
check(code, false, "test.cpp"); // C++ file => nullptr means NULL check(code, false, "test.cpp"); // C++ file => nullptr means NULL
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: i\n" ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: i\n", errout.str());
"[test.cpp:4]: (error) Null pointer dereference\n", errout.str());
check(code, false, "test.c"); // C file => nullptr does not mean NULL check(code, false, "test.c"); // C file => nullptr does not mean NULL
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
@ -1198,8 +1196,7 @@ private:
" i++;\n" " i++;\n"
" };\n" " };\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Possible null pointer dereference: str\n" ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference: str\n", errout.str());
"[test.cpp:5]: (error) Null pointer dereference\n", errout.str());
} }
void nullpointer19() { // #3811 void nullpointer19() { // #3811
@ -1222,7 +1219,7 @@ private:
" if (x) p = q;\n" " if (x) p = q;\n"
" if (y ? p->x : p->y) { }\n" " if (y ? p->x : p->y) { }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (warning) Possible null pointer dereference: p\n", errout.str());
} }
void nullpointer21() { // #4038 - fp: if (x) p=q; else return; void nullpointer21() { // #4038 - fp: if (x) p=q; else return;
@ -1260,7 +1257,7 @@ private:
" if (data == 1 && array[i] == 0)\n" " if (data == 1 && array[i] == 0)\n"
" std::cout << \"test\";\n" " std::cout << \"test\";\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: array\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: array\n", errout.str());
} }
void nullpointer26() { // #3589 void nullpointer26() { // #3589
@ -1291,8 +1288,7 @@ private:
" *pointer_=0;\n" " *pointer_=0;\n"
" return *this;\n" " return *this;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:8]: (error) Possible null pointer dereference: pointer_\n" ASSERT_EQUALS("[test.cpp:8]: (error) Null pointer dereference: pointer_\n", errout.str());
"[test.cpp:8]: (error) Null pointer dereference\n", errout.str());
} }
void nullpointer28() { // #6491 void nullpointer28() { // #6491
@ -1303,7 +1299,7 @@ private:
" return i;\n" " return i;\n"
"}\n" "}\n"
"int main(){f(0);}\n", true); "int main(){f(0);}\n", true);
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (warning) Possible null pointer dereference: s\n", errout.str());
} }
void nullpointer30() { // #6392 void nullpointer30() { // #6392
@ -1347,7 +1343,7 @@ private:
" }\n" " }\n"
" return p;\n" " return p;\n"
"}", true); "}", true);
ASSERT_EQUALS("[test.cpp:7]: (error) Possible null pointer dereference: p\n" ASSERT_EQUALS("[test.cpp:7]: (warning) Possible null pointer dereference: p\n"
"[test.cpp:7]: (error) Null pointer dereference\n", errout.str()); "[test.cpp:7]: (error) Null pointer dereference\n", errout.str());
} }
@ -1756,8 +1752,7 @@ private:
" int* p = 0;\n" " int* p = 0;\n"
" return p[4];\n" " return p[4];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p\n" ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: p\n", errout.str());
"[test.cpp:3]: (error) Null pointer dereference\n", errout.str());
check("void f() {\n" check("void f() {\n"
" typeof(*NULL) y;\n" " typeof(*NULL) y;\n"
@ -1804,7 +1799,7 @@ private:
" char* s = 0;\n" " char* s = 0;\n"
" printf(\"%s\", s);\n" " printf(\"%s\", s);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: s\n", errout.str());
check("void f() {\n" check("void f() {\n"
" char *s = 0;\n" " char *s = 0;\n"
@ -1826,7 +1821,7 @@ private:
" char* s = 0;\n" " char* s = 0;\n"
" printf(\"%u%s\", 123, s);\n" " printf(\"%u%s\", 123, s);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: s\n", errout.str());
check("void f() {\n" check("void f() {\n"
@ -1893,7 +1888,7 @@ private:
" int* iVal = 0;\n" " int* iVal = 0;\n"
" sscanf(dummy, \"%d\", iVal);\n" " sscanf(dummy, \"%d\", iVal);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: iVal\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: iVal\n", errout.str());
check("void f(char *dummy) {\n" check("void f(char *dummy) {\n"
" int* iVal;\n" " int* iVal;\n"
@ -1919,7 +1914,7 @@ private:
" if(g()) iVal = g();\n" " if(g()) iVal = g();\n"
" return iVal[0];\n" " return iVal[0];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: iVal\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (warning) Possible null pointer dereference: iVal\n", errout.str());
check("int foo(int* iVal) {\n" check("int foo(int* iVal) {\n"
" return iVal[0];\n" " return iVal[0];\n"
@ -2005,8 +2000,8 @@ private:
" std::string s5(p);\n" " std::string s5(p);\n"
" foo(std::string(p));\n" " foo(std::string(p));\n"
"}", true); "}", true);
ASSERT_EQUALS("[test.cpp:9]: (error) Possible null pointer dereference: p\n" ASSERT_EQUALS("[test.cpp:9]: (error) Null pointer dereference: p\n"
"[test.cpp:10]: (error) Possible null pointer dereference: p\n" "[test.cpp:10]: (error) Null pointer dereference: p\n"
"[test.cpp:3]: (error) Null pointer dereference\n" "[test.cpp:3]: (error) Null pointer dereference\n"
"[test.cpp:5]: (error) Null pointer dereference\n" "[test.cpp:5]: (error) Null pointer dereference\n"
"[test.cpp:7]: (error) Null pointer dereference\n" "[test.cpp:7]: (error) Null pointer dereference\n"
@ -2025,10 +2020,10 @@ private:
" foo(p == s2);\n" " foo(p == s2);\n"
" foo(p == s3);\n" " foo(p == s3);\n"
"}", true); "}", true);
ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: p\n" ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: p\n"
"[test.cpp:5]: (error) Possible null pointer dereference: p\n" "[test.cpp:5]: (error) Null pointer dereference: p\n"
"[test.cpp:7]: (error) Possible null pointer dereference: p\n" "[test.cpp:7]: (error) Null pointer dereference: p\n"
"[test.cpp:8]: (error) Possible null pointer dereference: p\n", errout.str()); "[test.cpp:8]: (error) Null pointer dereference: p\n", errout.str());
check("void f(std::string s1, const std::string& s2, const std::string* s3) {\n" check("void f(std::string s1, const std::string& s2, const std::string* s3) {\n"
" void* p = 0;\n" " void* p = 0;\n"
@ -2098,8 +2093,8 @@ private:
" if(q == 0)\n" " if(q == 0)\n"
" oss << foo << q;\n" " oss << foo << q;\n"
"}", false); "}", false);
ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p\n" ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: p\n"
"[test.cpp:4]: (error) Possible null pointer dereference: p\n" "[test.cpp:4]: (error) Null pointer dereference: p\n"
"[test.cpp:6] -> [test.cpp:5]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str()); "[test.cpp:6] -> [test.cpp:5]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str());
check("void f(const char* p) {\n" check("void f(const char* p) {\n"