tests: cleanup and reordering
This commit is contained in:
parent
953693ac2e
commit
0f83b0b9ea
526
tests.cpp
526
tests.cpp
|
@ -117,17 +117,88 @@ static void check(void (chk)(),
|
|||
|
||||
static void buffer_overrun()
|
||||
{
|
||||
// test1: numeric array index
|
||||
// test2: variable array index (for-loop)
|
||||
// test3: creating several arrays with the same names.
|
||||
// test4: using strcpy -> check string length
|
||||
// test5: constant array index
|
||||
// test6: calculated array index that is out of bounds
|
||||
// test7: unknown string length
|
||||
// test8: struct member..
|
||||
// There are 3 sections..
|
||||
// 1. No errors
|
||||
// 2. Array index out of bounds
|
||||
// 3. Buffer overrun
|
||||
|
||||
|
||||
const char *code;
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// NO ERRORS
|
||||
////////////////////////////////////////////////
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "void f1(char *str)\n"
|
||||
"{\n"
|
||||
" strcpy(buf,str);\n"
|
||||
"}\n"
|
||||
"void f2(char *str)\n"
|
||||
"{\n"
|
||||
" strcat(buf,str);\n"
|
||||
"}\n"
|
||||
"void f3(char *str)\n"
|
||||
"{\n"
|
||||
" sprintf(buf,\"%s\",str);\n"
|
||||
"}\n"
|
||||
"void f4(const char str[])\n"
|
||||
"{\n"
|
||||
" strcpy(buf, str);\n"
|
||||
"}\n";
|
||||
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" char data[1];\n"
|
||||
" return abc.data[1];\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
// TODO
|
||||
/*
|
||||
code = "static void memclr( char *data, const int bytes )\n"
|
||||
"{\n"
|
||||
" for (int i = 0; i < bytes; i++)\n"
|
||||
" data[i] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
" memclr( str, 5 ); // OK\n"
|
||||
" memclr( str+1, 5 ); // ERROR\n"
|
||||
" memclr( str, 6 ); // ERROR\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Array index out of bounds
|
||||
////////////////////////////////////////////////
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char str[0x10];\n"
|
||||
|
@ -156,33 +227,6 @@ static void buffer_overrun()
|
|||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:5]: Array index out of bounds\n" );
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char str[3];\n"
|
||||
" strcpy(str, \"abc\");\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:4]: Buffer overrun\n" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" int i[10];\n"
|
||||
|
@ -192,27 +236,6 @@ static void buffer_overrun()
|
|||
|
||||
|
||||
|
||||
|
||||
code = "void f1(char *str)\n"
|
||||
"{\n"
|
||||
" strcpy(buf,str);\n"
|
||||
"}\n"
|
||||
"void f2(char *str)\n"
|
||||
"{\n"
|
||||
" strcat(buf,str);\n"
|
||||
"}\n"
|
||||
"void f3(char *str)\n"
|
||||
"{\n"
|
||||
" sprintf(buf,\"%s\",str);\n"
|
||||
"}\n"
|
||||
"void f4(const char str[])\n"
|
||||
"{\n"
|
||||
" strcpy(buf, str);\n"
|
||||
"}\n";
|
||||
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
|
@ -226,6 +249,19 @@ static void buffer_overrun()
|
|||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:9]: Array index out of bounds\n" );
|
||||
|
||||
|
||||
|
||||
code = "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:8]: Array index out of bounds\n" );
|
||||
|
||||
|
||||
code = "const int SIZE = 10;\n"
|
||||
"\n"
|
||||
"struct ABC\n"
|
||||
|
@ -242,31 +278,6 @@ static void buffer_overrun()
|
|||
|
||||
|
||||
|
||||
code = "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:8]: Array index out of bounds\n" );
|
||||
|
||||
|
||||
|
||||
code = "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" strcpy( abc->str, \"abcdef\" );\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:8]: Buffer overrun\n" );
|
||||
|
||||
|
||||
|
||||
code = "static void memclr( char *data )\n"
|
||||
"{\n"
|
||||
|
@ -318,36 +329,6 @@ static void buffer_overrun()
|
|||
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" char data[1];\n"
|
||||
" return abc.data[1];\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO
|
||||
/*
|
||||
code = "static void memclr( char *data, const int bytes )\n"
|
||||
"{\n"
|
||||
" for (int i = 0; i < bytes; i++)\n"
|
||||
" data[i] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
" memclr( str, 5 ); // OK\n"
|
||||
" memclr( str+1, 5 ); // ERROR\n"
|
||||
" memclr( str, 6 ); // ERROR\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "" );
|
||||
*/
|
||||
|
||||
|
||||
// TODO
|
||||
/*
|
||||
const char test[] = "class Fred\n"
|
||||
|
@ -364,6 +345,33 @@ static void buffer_overrun()
|
|||
check( CheckBufferOverrun, __LINE__, test, "[test.cpp:5]: Array index out of bounds\n" );
|
||||
*/
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Buffer overrun
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char str[3];\n"
|
||||
" strcpy(str, \"abc\");\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:4]: Buffer overrun\n" );
|
||||
|
||||
|
||||
code = "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" strcpy( abc->str, \"abcdef\" );\n"
|
||||
"}\n";
|
||||
check( CheckBufferOverrun, __LINE__, code, "[test.cpp:8]: Buffer overrun\n" );
|
||||
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -441,19 +449,24 @@ static void operator_eq()
|
|||
|
||||
static void memleak_in_function()
|
||||
{
|
||||
// test1: 'new' but not 'delete'
|
||||
// test2: Return allocated memory
|
||||
// test3: check all execution paths
|
||||
// test4: check all execution paths
|
||||
// test5: check all execution paths
|
||||
// test6: check all execution paths
|
||||
// test7: check all execution paths
|
||||
// test8: check all execution paths
|
||||
// test9: mismatching allocation / deallocation
|
||||
// There are 2 sections:
|
||||
// * Simple testcases
|
||||
// * if else
|
||||
// * for/while..
|
||||
// * mismatching allocation and deallocation
|
||||
// * garbage collection
|
||||
// * struct members
|
||||
// * function calls
|
||||
|
||||
|
||||
const char *code;
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Simple testcases
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" int *a = new int[10];\n"
|
||||
|
@ -461,8 +474,6 @@ static void memleak_in_function()
|
|||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: a\n" );
|
||||
|
||||
|
||||
|
||||
|
||||
code = "Fred *NewFred()\n"
|
||||
"{\n"
|
||||
" Fred *f = new Fred;\n"
|
||||
|
@ -471,6 +482,79 @@ static void memleak_in_function()
|
|||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" char *s = new char[100];\n"
|
||||
" return (char *)s;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" char *str2 = (char *)str;\n"
|
||||
" free(str2);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// if else
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" int *a = new int[10];\n"
|
||||
" if (a)\n"
|
||||
" {\n"
|
||||
" delete a;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" if (somecondition)\n"
|
||||
" {\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" free(str);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:6]: Memory leak: str\n" );
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" if (a==b)\n"
|
||||
" {\n"
|
||||
" free(str);\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: str\n" );
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = new char[10];\n"
|
||||
" if (a==b)\n"
|
||||
" {\n"
|
||||
" delete [] str;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" delete [] str;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO
|
||||
|
@ -490,6 +574,41 @@ static void memleak_in_function()
|
|||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
*/
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" char *s = new char[100];\n"
|
||||
" if ( a == b )\n"
|
||||
" {\n"
|
||||
" return s;\n"
|
||||
" }\n"
|
||||
" return NULL;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:8]: Memory leak: s\n" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// for/while
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" while (condition)\n"
|
||||
" {\n"
|
||||
" if (condition)\n"
|
||||
" {\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" free(str);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -507,61 +626,13 @@ static void memleak_in_function()
|
|||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" while (condition)\n"
|
||||
" {\n"
|
||||
" if (condition)\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" free(str);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" if (a==b)\n"
|
||||
" {\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" free(str);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:6]: Memory leak: str\n" );
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" if (a==b)\n"
|
||||
" {\n"
|
||||
" free(str);\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: str\n" );
|
||||
|
||||
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
" char *str = new char[10];\n"
|
||||
" if (a==b)\n"
|
||||
" {\n"
|
||||
" delete [] str;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" delete [] str;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// mismatching allocation and deallocation
|
||||
////////////////////////////////////////////////
|
||||
|
||||
code = "void f()\n"
|
||||
"{\n"
|
||||
|
@ -572,33 +643,13 @@ static void memleak_in_function()
|
|||
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" struct acpi_object_list *obj_list;\n"
|
||||
" obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: obj_list\n" );
|
||||
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" char *s = new char[100];\n"
|
||||
" return s;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" Fred *fred = new Fred;\n"
|
||||
" free( fred->Name );\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: fred\n" );
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Garbage collection
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
|
@ -609,6 +660,38 @@ static void memleak_in_function()
|
|||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "struct abc\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct abc *abc1 = new abc;\n"
|
||||
" p = &abc1->a;\n" // p may be part of a garbage collector
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// struct members
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" Fred *fred = new Fred;\n"
|
||||
" free( fred->Name );\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:3]: Memory leak: fred\n" );
|
||||
|
||||
|
||||
/* TODO
|
||||
code = "struct Fred\n"
|
||||
"{\n"
|
||||
|
@ -625,58 +708,13 @@ static void memleak_in_function()
|
|||
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" char *s = new char[100];\n"
|
||||
" return (char *)s;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "static char *f()\n"
|
||||
"{\n"
|
||||
" char *s = new char[100];\n"
|
||||
" if ( a == b )\n"
|
||||
" {\n"
|
||||
" return s;\n"
|
||||
" }\n"
|
||||
" return NULL;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "[test.cpp:8]: Memory leak: s\n" );
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" char *str = strdup(\"hello\");\n"
|
||||
" char *str2 = (char *)str;\n"
|
||||
" free(str2);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "static void f()\n"
|
||||
"{\n"
|
||||
" char *str;\n"
|
||||
" if ((str = (char *)malloc(123,33)) == NULL)\n"
|
||||
" return;\n"
|
||||
" free(str);\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
|
||||
|
||||
code = "struct abc\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct abc *abc1 = new abc;\n"
|
||||
" p = &abc1->a;\n"
|
||||
"}\n";
|
||||
check( CheckMemoryLeak, __LINE__, code, "" );
|
||||
////////////////////////////////////////////////
|
||||
// function calls
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
code = "static char *dmalloc()\n"
|
||||
|
|
Loading…
Reference in New Issue