testuninitvar: use new checking instead of executionpath

This commit is contained in:
Daniel Marjamäki 2015-07-23 17:20:11 +02:00
parent 856d496c71
commit 995c4196b5
1 changed files with 136 additions and 215 deletions

View File

@ -44,7 +44,6 @@ private:
TEST_CASE(uninitvar_references); // references TEST_CASE(uninitvar_references); // references
TEST_CASE(uninitvar_return); // return TEST_CASE(uninitvar_return); // return
TEST_CASE(uninitvar_strncpy); // strncpy doesn't always null-terminate TEST_CASE(uninitvar_strncpy); // strncpy doesn't always null-terminate
TEST_CASE(uninitvar_memset); // not null-terminated
TEST_CASE(uninitvar_memset_nonchar); TEST_CASE(uninitvar_memset_nonchar);
TEST_CASE(uninitvar_memset_char_access); TEST_CASE(uninitvar_memset_char_access);
TEST_CASE(uninitvar_func); // analyse functions TEST_CASE(uninitvar_func); // analyse functions
@ -78,22 +77,6 @@ private:
TEST_CASE(deadPointer); TEST_CASE(deadPointer);
} }
void checkUninitVar(const char code[], const char filename[] = "test.cpp") {
// Clear the error buffer..
errout.str("");
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, filename);
tokenizer.simplifyTokenList2();
// Check code..
CheckUninitVar check(&tokenizer, &settings, this);
check.executionPaths();
}
/** New checking that doesn't rely on ExecutionPath */ /** New checking that doesn't rely on ExecutionPath */
void checkUninitVar2(const char code[], const char fname[] = "test.cpp", bool verify = true, bool debugwarnings = false) { void checkUninitVar2(const char code[], const char fname[] = "test.cpp", bool verify = true, bool debugwarnings = false) {
// Clear the error buffer.. // Clear the error buffer..
@ -525,23 +508,6 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void a()\n"
"{\n"
" struct S *s;\n"
" FOREACH() { }\n"
" s->x = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: s\n", errout.str());
checkUninitVar("void a()\n"
"{\n"
" struct S *s1;\n"
" struct S *s2;\n"
" FOREACH(s1) { }\n"
" s2->x = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: s2\n", errout.str());
// #1533 // #1533
checkUninitVarB("char a()\n" checkUninitVarB("char a()\n"
"{\n" "{\n"
@ -610,12 +576,12 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" int a[10];\n" " int a[10];\n"
" a[0] = 10 - a[1];\n" " a[0] = 10 - a[1];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", "", errout.str());
// goto/setjmp/longjmp.. // goto/setjmp/longjmp..
checkUninitVarB("void foo(int x)\n" checkUninitVarB("void foo(int x)\n"
@ -1065,25 +1031,6 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// while..
checkUninitVar("int f()\n"
"{\n"
" int i;\n"
" while (fgets())\n"
" i = 1;\n"
" return i;"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: i\n", errout.str());
checkUninitVar2("void f(int i)\n"
"{\n"
" int a;\n"
" while (i < 10)\n"
" i++;\n"
" a++;"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: a\n", errout.str());
// Ticket #2226: C++0x loop // Ticket #2226: C++0x loop
checkUninitVarB("void f() {\n" checkUninitVarB("void f() {\n"
" container c;\n" " container c;\n"
@ -1113,7 +1060,7 @@ private:
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: pItem\n", errout.str());
// #2231 - conditional initialization in loop.. // #2231 - conditional initialization in loop..
checkUninitVar("int foo(char *a) {\n" checkUninitVar2("int foo(char *a) {\n"
" int x;\n" " int x;\n"
"\n" "\n"
" for (int i = 0; i < 10; ++i) {\n" " for (int i = 0; i < 10; ++i) {\n"
@ -1125,7 +1072,7 @@ private:
"\n" "\n"
" return x;\n" " return x;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:11]: (error) Uninitialized variable: x\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:11]: (error) Uninitialized variable: x\n", "", errout.str());
// Ticket #2796 // Ticket #2796
checkUninitVarB("void foo() {\n" checkUninitVarB("void foo() {\n"
@ -1150,7 +1097,7 @@ private:
// switch.. // switch..
void uninitvar_switch() { void uninitvar_switch() {
checkUninitVar("void f(int x)\n" checkUninitVar2("void f(int x)\n"
"{\n" "{\n"
" short c;\n" " short c;\n"
" switch(x) {\n" " switch(x) {\n"
@ -1159,7 +1106,7 @@ private:
" break;\n" " break;\n"
" };\n" " };\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: c\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: c\n", "", errout.str());
checkUninitVarB("char * f()\n" checkUninitVarB("char * f()\n"
"{\n" "{\n"
@ -1197,21 +1144,6 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// No segmentation fault
checkUninitVar("void a() try\n"
"{\n"
" {\n"
" while (1) {\n"
" switch (1) {\n"
" case 1: {\n"
" int i;\n"
" }\n"
" }\n"
" }\n"
" } catch (...) {\n"
" }\n"
"}");
// #1855 - switch(foo(&x)) // #1855 - switch(foo(&x))
checkUninitVarB("int a()\n" checkUninitVarB("int a()\n"
"{\n" "{\n"
@ -1241,12 +1173,12 @@ private:
// arrays.. // arrays..
void uninitvar_arrays() { void uninitvar_arrays() {
checkUninitVar("int f()\n" checkUninitVar2("int f()\n"
"{\n" "{\n"
" char a[10];\n" " char a[10];\n"
" a[a[0]] = 0;\n" " a[a[0]] = 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", "", errout.str());
checkUninitVar2("int f() {\n" checkUninitVar2("int f() {\n"
" char a[10];\n" " char a[10];\n"
@ -1351,11 +1283,11 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void f() {\n" // Ticket #3050 checkUninitVar2("void f() {\n" // Ticket #3050
" char a[2];\n" " char a[2];\n"
" printf(\"%s\", a);\n" " printf(\"%s\", a);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", "", errout.str());
checkUninitVarB("void f() {\n" // Ticket #5108 (fp) checkUninitVarB("void f() {\n" // Ticket #5108 (fp)
" const char *a;\n" " const char *a;\n"
@ -1409,13 +1341,13 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("int foo() {\n" checkUninitVar2("int foo() {\n"
" int a[1];\n" " int a[1];\n"
" return a[0];\n" " return a[0];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", "", errout.str());
checkUninitVar("int foo() {\n" checkUninitVar2("int foo() {\n"
" int a[2][2];\n" " int a[2][2];\n"
" return a[0][1];\n" " return a[0][1];\n"
"}"); "}");
@ -1444,26 +1376,26 @@ private:
"};"); "};");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s1\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s1\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char *p = malloc(64);\n" " char *p = malloc(64);\n"
" int x = p[0];\n" " int x = p[0];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", "", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char *p = malloc(64);\n" " char *p = malloc(64);\n"
" if (p[0]) { }\n" " if (p[0]) { }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", "", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char *p = malloc(64);\n" " char *p = malloc(64);\n"
" return p[0];\n" " return p[0];\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", "", errout.str());
checkUninitVarB("void f()\n" checkUninitVarB("void f()\n"
"{\n" "{\n"
@ -1500,7 +1432,7 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void foo()\n" checkUninitVar2("void foo()\n"
"{\n" "{\n"
" char *a;\n" " char *a;\n"
" if (a);\n" " if (a);\n"
@ -1543,14 +1475,14 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char *s = malloc(100);\n" " char *s = malloc(100);\n"
" if (!s)\n" " if (!s)\n"
" return;\n" " return;\n"
" char c = *s;\n" " char c = *s;\n"
"};"); "};");
ASSERT_EQUALS("[test.cpp:6]: (error) Memory is allocated but not initialized: s\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Memory is allocated but not initialized: s\n", "", errout.str());
// #3708 - false positive when using ptr typedef // #3708 - false positive when using ptr typedef
checkUninitVarB("void f() {\n" checkUninitVarB("void f() {\n"
@ -1660,7 +1592,7 @@ private:
// enum.. // enum..
void uninitvar_enum() { void uninitvar_enum() {
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" enum AB { a, b };\n" " enum AB { a, b };\n"
" AB ab;\n" " AB ab;\n"
@ -1818,21 +1750,24 @@ private:
// strncpy doesn't always null-terminate.. // strncpy doesn't always null-terminate..
void uninitvar_strncpy() { void uninitvar_strncpy() {
checkUninitVar("void f()\n" // TODO: Add this checking
// Can it be added without hardcoding?
checkUninitVar2("void f()\n"
"{\n" "{\n"
" char a[100];\n" " char a[100];\n"
" strncpy(a, s, 20);\n" " strncpy(a, s, 20);\n"
" strncat(a, s, 20);\n" " strncat(a, s, 20);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Dangerous usage of 'a' (strncpy doesn't always null-terminate it).\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Dangerous usage of 'a' (strncpy doesn't always null-terminate it).\n", "", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char a[100];\n" " char a[100];\n"
" strncpy(a, \"hello\", 3);\n" " strncpy(a, \"hello\", 3);\n"
" strncat(a, \"world\", 20);\n" " strncat(a, \"world\", 20);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Dangerous usage of 'a' (strncpy doesn't always null-terminate it).\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Dangerous usage of 'a' (strncpy doesn't always null-terminate it).\n", "", errout.str());
checkUninitVarB("void f()\n" checkUninitVarB("void f()\n"
"{\n" "{\n"
@ -1876,18 +1811,8 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
// initialization with memset (not 0-terminating string)..
void uninitvar_memset() {
checkUninitVar("void f() {\n"
" char a[20];\n"
" memset(a, 'a', 20);\n"
" strcat(a, s);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Dangerous usage of 'a' (not null-terminated).\n", errout.str());
}
void uninitvar_memset_nonchar() { void uninitvar_memset_nonchar() {
checkUninitVar("void f() {\n" checkUninitVar2("void f() {\n"
" int a[20];\n" " int a[20];\n"
" memset(a, 1, 20);\n" " memset(a, 1, 20);\n"
" a[0] |= 2;\n" " a[0] |= 2;\n"
@ -1896,7 +1821,7 @@ private:
} }
void uninitvar_memset_char_access() { void uninitvar_memset_char_access() {
checkUninitVar("void f() {\n" checkUninitVar2("void f() {\n"
" unsigned char c[10];\n" " unsigned char c[10];\n"
" memset(c, 32, 10);\n" " memset(c, 32, 10);\n"
" unsigned char value = c[3];\n" " unsigned char value = c[3];\n"
@ -1964,19 +1889,17 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f() {\n"
"{\n"
" FILE *f;\n" " FILE *f;\n"
" fflush(f);\n" " fflush(f);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: f\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: f\n", errout.str());
checkUninitVar2("void f()\n" checkUninitVar2("void f() {\n"
"{\n"
" int i;\n" " int i;\n"
" x(i+2);\n" " x(i+2);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: i\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: i\n", errout.str());
checkUninitVarB("void f()\n" checkUninitVarB("void f()\n"
"{\n" "{\n"
@ -1993,19 +1916,17 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVarB("void foo()\n" checkUninitVarB("void foo() {\n"
"{\n"
" Foo *p;\n" " Foo *p;\n"
" x = bar(sizeof(*p));\n" " x = bar(sizeof(*p));\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("void foo()\n" checkUninitVar2("void foo() {\n"
"{\n"
" Foo *p;\n" " Foo *p;\n"
" x = bar(p->begin());\n" " x = bar(p->begin());\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: p\n", errout.str());
checkUninitVar2("int foo(int x) { return x; }\n" checkUninitVar2("int foo(int x) { return x; }\n"
"void f2()\n" "void f2()\n"
@ -2015,7 +1936,7 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: x\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVar("void foo(const char *s)\n" checkUninitVar2("void foo(const char *s)\n"
"{\n" "{\n"
" char *p;\n" " char *p;\n"
" memcpy(p, s, 100);\n" " memcpy(p, s, 100);\n"
@ -2029,7 +1950,7 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("int calc(const int *p, int n);\n" checkUninitVar2("int calc(const int *p, int n);\n"
"void f() {\n" "void f() {\n"
" int x[10];\n" " int x[10];\n"
" calc(x,10);\n" " calc(x,10);\n"