Fixed #3771
Stronger testing for false positives in inconclusive checking in checknullpointer.cpp
This commit is contained in:
parent
5d6a257c86
commit
8e362ad5f7
|
@ -372,6 +372,10 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym
|
||||||
if (Token::Match(tok->previous(), "return|= %var% ;"))
|
if (Token::Match(tok->previous(), "return|= %var% ;"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// (void)var
|
||||||
|
if (Token::Match(tok->previous(), "[{;}] %var% ;"))
|
||||||
|
return false;
|
||||||
|
|
||||||
// unknown if it's a dereference
|
// unknown if it's a dereference
|
||||||
unknown = true;
|
unknown = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(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
|
||||||
TEST_CASE(gcc_statement_expression); // Don't crash
|
TEST_CASE(gcc_statement_expression); // Don't crash
|
||||||
|
@ -226,7 +227,7 @@ private:
|
||||||
" sizeof(*list);\n"
|
" sizeof(*list);\n"
|
||||||
" if (!list)\n"
|
" if (!list)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// ticket #2245 - sizeof doesn't dereference
|
// ticket #2245 - sizeof doesn't dereference
|
||||||
|
@ -234,7 +235,7 @@ private:
|
||||||
" if (!p) {\n"
|
" if (!p) {\n"
|
||||||
" int sz = sizeof(p->x);\n"
|
" int sz = sizeof(p->x);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,7 @@ private:
|
||||||
" Fred fred;\n"
|
" Fred fred;\n"
|
||||||
" while (fred);\n"
|
" while (fred);\n"
|
||||||
" fred.hello();\n"
|
" fred.hello();\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,13 +323,13 @@ private:
|
||||||
" abc = abc->next;\n"
|
" abc = abc->next;\n"
|
||||||
" if (!abc)\n"
|
" if (!abc)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f(struct ABC *abc) {\n"
|
check("void f(struct ABC *abc) {\n"
|
||||||
" abc = (ABC *)(abc->_next);\n"
|
" abc = (ABC *)(abc->_next);\n"
|
||||||
" if (abc) { }"
|
" if (abc) { }"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// reassign struct..
|
// reassign struct..
|
||||||
|
@ -338,7 +339,7 @@ private:
|
||||||
" abc = abc->next;\n"
|
" abc = abc->next;\n"
|
||||||
" if (!abc)\n"
|
" if (!abc)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void foo(struct ABC *abc)\n"
|
check("void foo(struct ABC *abc)\n"
|
||||||
|
@ -347,7 +348,7 @@ private:
|
||||||
" f(&abc);\n"
|
" f(&abc);\n"
|
||||||
" if (!abc)\n"
|
" if (!abc)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// goto..
|
// goto..
|
||||||
|
@ -535,7 +536,7 @@ private:
|
||||||
" int **p = f();\n"
|
" int **p = f();\n"
|
||||||
" if (!p)\n"
|
" if (!p)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void foo(int *p)\n"
|
check("void foo(int *p)\n"
|
||||||
|
@ -554,7 +555,7 @@ private:
|
||||||
" int a = 2 * x;"
|
" int a = 2 * x;"
|
||||||
" if (x == 0)\n"
|
" if (x == 0)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void foo(int *p)\n"
|
check("void foo(int *p)\n"
|
||||||
|
@ -711,7 +712,7 @@ private:
|
||||||
" int c = sizeof(test[0]);\n"
|
" int c = sizeof(test[0]);\n"
|
||||||
" if (!test)\n"
|
" if (!test)\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// #3023 - checked deref
|
// #3023 - checked deref
|
||||||
|
@ -966,14 +967,14 @@ private:
|
||||||
" for (int i = 0; i < 3; i++) {\n"
|
" for (int i = 0; i < 3; i++) {\n"
|
||||||
" if (a && (p[i] == '1'));\n"
|
" if (a && (p[i] == '1'));\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// ticket #2251: taking the address of member
|
// ticket #2251: taking the address of member
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" Fred *fred = 0;\n"
|
" Fred *fred = 0;\n"
|
||||||
" int x = &fred->x;\n"
|
" int x = &fred->x;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// ticket #3220: calling member function
|
// ticket #3220: calling member function
|
||||||
|
@ -990,14 +991,14 @@ private:
|
||||||
" if (x)\n"
|
" if (x)\n"
|
||||||
" p = q;\n"
|
" p = q;\n"
|
||||||
" if (p && *p) { }\n"
|
" if (p && *p) { }\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int *p = NULL;\n"
|
" int *p = NULL;\n"
|
||||||
" if (x)\n"
|
" if (x)\n"
|
||||||
" p = q;\n"
|
" p = q;\n"
|
||||||
" if (!p || *p) { }\n"
|
" if (!p || *p) { }\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int *p = NULL;\n"
|
" int *p = NULL;\n"
|
||||||
|
@ -1063,7 +1064,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" wxLongLong x = 0;\n"
|
" wxLongLong x = 0;\n"
|
||||||
" int y = x.GetValue();\n"
|
" int y = x.GetValue();\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,7 +1153,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" int* i = nullptr;\n"
|
" int* i = nullptr;\n"
|
||||||
" return *i;\n"
|
" return *i;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1209,7 +1210,7 @@ private:
|
||||||
" int *p = 0;\n"
|
" int *p = 0;\n"
|
||||||
" bar(&p);\n"
|
" bar(&p);\n"
|
||||||
" *p = 0;\n"
|
" *p = 0;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,13 +1218,13 @@ private:
|
||||||
check("int foo() {\n"
|
check("int foo() {\n"
|
||||||
" int *p = 0;\n"
|
" int *p = 0;\n"
|
||||||
" return (!p || *p);\n"
|
" return (!p || *p);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("int foo() {\n"
|
check("int foo() {\n"
|
||||||
" int *p = 0;\n"
|
" int *p = 0;\n"
|
||||||
" return p && *p;\n"
|
" return p && *p;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1241,6 +1242,14 @@ 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 nullpointer_castToVoid() { // #3771
|
||||||
|
check("void f () {\n"
|
||||||
|
" int *buf = NULL;\n"
|
||||||
|
" (void)buf;\n"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Check if pointer is null and the dereference it
|
// Check if pointer is null and the dereference it
|
||||||
void pointerCheckAndDeRef() {
|
void pointerCheckAndDeRef() {
|
||||||
check("void foo(char *p) {\n"
|
check("void foo(char *p) {\n"
|
||||||
|
@ -1351,14 +1360,14 @@ private:
|
||||||
" if (!p) {\n"
|
" if (!p) {\n"
|
||||||
" switch (x) { }\n"
|
" switch (x) { }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void foo(char *p) {\n"
|
check("void foo(char *p) {\n"
|
||||||
" if (!p) {\n"
|
" if (!p) {\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" return *x;\n"
|
" return *x;\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("int foo(int *p) {\n"
|
check("int foo(int *p) {\n"
|
||||||
|
@ -1445,7 +1454,7 @@ private:
|
||||||
"\n"
|
"\n"
|
||||||
"void Fred::b() {\n"
|
"void Fred::b() {\n"
|
||||||
" wilma->Reload();\n"
|
" wilma->Reload();\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void test(int *i) {\n"
|
check("void test(int *i) {\n"
|
||||||
|
@ -1454,7 +1463,7 @@ private:
|
||||||
" } else {\n"
|
" } else {\n"
|
||||||
" int b = *i;\n"
|
" int b = *i;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// #2696 - false positives nr 1
|
// #2696 - false positives nr 1
|
||||||
|
@ -1467,7 +1476,7 @@ private:
|
||||||
"\n"
|
"\n"
|
||||||
" if (pFoo)\n"
|
" if (pFoo)\n"
|
||||||
" bar();\n"
|
" bar();\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// #2696 - false positives nr 2
|
// #2696 - false positives nr 2
|
||||||
|
@ -1480,7 +1489,7 @@ private:
|
||||||
" pFoo = pFoo->next;\n"
|
" pFoo = pFoo->next;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" len = sizeof(pFoo->data);\n"
|
" len = sizeof(pFoo->data);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// #2696 - false positives nr 3
|
// #2696 - false positives nr 3
|
||||||
|
@ -1493,7 +1502,7 @@ private:
|
||||||
" pFoo = pFoo->next;\n"
|
" pFoo = pFoo->next;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" len = decltype(*pFoo);\n"
|
" len = decltype(*pFoo);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("int foo(struct Fred *fred) {\n"
|
check("int foo(struct Fred *fred) {\n"
|
||||||
|
@ -1595,7 +1604,7 @@ private:
|
||||||
check("void f(struct fred_t *fred) {\n"
|
check("void f(struct fred_t *fred) {\n"
|
||||||
" if (!fred)\n"
|
" if (!fred)\n"
|
||||||
" int sz = sizeof fred->x;\n"
|
" int sz = sizeof fred->x;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// check in macro
|
// check in macro
|
||||||
|
@ -1625,13 +1634,13 @@ private:
|
||||||
// Ticket #2413 - it's ok to pass NULL to fflush
|
// Ticket #2413 - it's ok to pass NULL to fflush
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" fflush(NULL);\n"
|
" fflush(NULL);\n"
|
||||||
"}\n");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// Ticket #3126 - don't confuse member function with standard function
|
// Ticket #3126 - don't confuse member function with standard function
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" image1.fseek(0, SEEK_SET);\n"
|
" image1.fseek(0, SEEK_SET);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
|
@ -1653,7 +1662,7 @@ private:
|
||||||
// Ticket #2840
|
// Ticket #2840
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" int bytes = snprintf(0, 0, \"%u\", 1);\n"
|
" int bytes = snprintf(0, 0, \"%u\", 1);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1804,7 +1813,7 @@ private:
|
||||||
|
|
||||||
check("int foo(int* iVal) {\n"
|
check("int foo(int* iVal) {\n"
|
||||||
" return iVal[0];\n"
|
" return iVal[0];\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1814,20 +1823,20 @@ private:
|
||||||
"bool foo() {\n"
|
"bool foo() {\n"
|
||||||
" PolymorphicA* a = 0;\n"
|
" PolymorphicA* a = 0;\n"
|
||||||
" return typeid(*a) == typeid(*a);\n"
|
" return typeid(*a) == typeid(*a);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("struct NonPolymorphicA { ~A() {} };\n"
|
check("struct NonPolymorphicA { ~A() {} };\n"
|
||||||
"bool foo() {\n"
|
"bool foo() {\n"
|
||||||
" NonPolymorphicA* a = 0;\n"
|
" NonPolymorphicA* a = 0;\n"
|
||||||
" return typeid(*a) == typeid(*a);\n"
|
" return typeid(*a) == typeid(*a);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("bool foo() {\n"
|
check("bool foo() {\n"
|
||||||
" char* c = 0;\n"
|
" char* c = 0;\n"
|
||||||
" return typeid(*c) == typeid(*c);\n"
|
" return typeid(*c) == typeid(*c);\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1963,7 +1972,7 @@ private:
|
||||||
" char* p2 = 0;\n"
|
" char* p2 = 0;\n"
|
||||||
" std::cin >> (int)p;\n" // result casted
|
" std::cin >> (int)p;\n" // result casted
|
||||||
" std::cout << (int)p;\n"
|
" std::cout << (int)p;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f(const std::string& str) {\n"
|
check("void f(const std::string& str) {\n"
|
||||||
|
@ -1971,7 +1980,7 @@ private:
|
||||||
" std::istringstream istr(str);\n"
|
" std::istringstream istr(str);\n"
|
||||||
" istr >> std::hex >> ret;\n" // Read integer
|
" istr >> std::hex >> ret;\n" // Read integer
|
||||||
" return ret;\n"
|
" return ret;\n"
|
||||||
"}");
|
"}", true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue