Refactoring: CheckBufferOverrun refactorings. split up the checkScope into two separate functions. The ArrayInfo usage was improved. Also broke out for-loop handling into separate functions.

This commit is contained in:
Daniel Marjamäki 2010-04-21 18:33:21 +02:00
parent c26e619b23
commit 798aa84151
3 changed files with 621 additions and 392 deletions

File diff suppressed because it is too large Load Diff

View File

@ -98,7 +98,7 @@ public:
/** Check for negative index */ /** Check for negative index */
void negativeIndex(); void negativeIndex();
/** Check for buffer overruns - this is the function that performs the actual checking */ /** Check for buffer overruns */
void checkScope(const Token *tok, const std::vector<std::string> &varname, const int size, const int total_size, unsigned int varid); void checkScope(const Token *tok, const std::vector<std::string> &varname, const int size, const int total_size, unsigned int varid);
/** Information about N-dimensional array */ /** Information about N-dimensional array */
@ -122,6 +122,14 @@ public:
ArrayInfo(const ArrayInfo &); ArrayInfo(const ArrayInfo &);
const ArrayInfo & operator=(const ArrayInfo &ai); const ArrayInfo & operator=(const ArrayInfo &ai);
/**
* Create array info with specified data
* The intention is that this is only a temporary solution.. all
* checking should be based on ArrayInfo from the start and then
* this will not be needed as the declare can be used instead.
*/
ArrayInfo(unsigned int id, const std::string &name, unsigned int size1, unsigned int n);
/** /**
* Declare array - set info * Declare array - set info
* \param tok first token in array declaration * \param tok first token in array declaration
@ -143,6 +151,13 @@ public:
const std::string &varname; const std::string &varname;
}; };
/** Check for buffer overruns (based on ArrayInfo) */
void checkScope(const Token *tok, const ArrayInfo &arrayInfo);
/** Helper function used when parsing for-loops */
void parse_for_body(const Token *tok2, const ArrayInfo &arrayInfo, const std::string &strindex, bool condition_out_of_bounds, unsigned int counter_varid, const std::string &min_counter_value, const std::string &max_counter_value);
/** callstack - used during intra-function checking */ /** callstack - used during intra-function checking */
std::list<const Token *> _callStack; std::list<const Token *> _callStack;

View File

@ -310,7 +310,7 @@ private:
" for (i = 0; i < 100; i++)\n" " for (i = 0; i < 100; i++)\n"
" sum += val[i];\n" " sum += val[i];\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: val\n", errout.str());
} }
{ {
@ -321,7 +321,7 @@ private:
" for (i = 1; i < 100; i++)\n" " for (i = 1; i < 100; i++)\n"
" sum += val[i];\n" " sum += val[i];\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: val\n", errout.str());
} }
@ -333,7 +333,7 @@ private:
" for (i = a; i < 100; i++)\n" " for (i = a; i < 100; i++)\n"
" sum += val[i];\n" " sum += val[i];\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: val\n", errout.str());
} }
{ {
@ -457,7 +457,8 @@ private:
" char str[5];\n" " char str[5];\n"
" memclr( str ); // ERROR\n" " memclr( str ); // ERROR\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("static void memclr( int i, char *data )\n" check("static void memclr( int i, char *data )\n"
"{\n" "{\n"
@ -469,7 +470,8 @@ private:
" char str[5];\n" " char str[5];\n"
" memclr( 0, str ); // ERROR\n" " memclr( 0, str ); // ERROR\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("static void memclr( int i, char *data )\n" check("static void memclr( int i, char *data )\n"
"{\n" "{\n"
@ -496,8 +498,7 @@ private:
" char str[5];\n" " char str[5];\n"
" memclr( str, 5 ); // ERROR\n" " memclr( str, 5 ); // ERROR\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (possible error) Array index out of bounds\n", errout.str()); ASSERT_EQUALS("", errout.str());
TODO_ASSERT_EQUALS("", errout.str());
} }
@ -876,7 +877,7 @@ private:
" for (int i = 3; 0 <= i; i--)\n" " for (int i = 3; 0 <= i; i--)\n"
" a[i] = i;\n" " a[i] = i;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds: a\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -908,8 +909,7 @@ private:
" char a[2][2];\n" " char a[2][2];\n"
" a[2][1] = 'a';\n" " a[2][1] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index 2 out of bounds\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -917,15 +917,14 @@ private:
" a[1][2] = 'a';\n" " a[1][2] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("", errout.str()); // catch changes
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2]' index 2 out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[2][2][2];\n" " char a[2][2][2];\n"
" a[2][1][1] = 'a';\n" " a[2][1][1] = 'a';\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); // catch changes ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[2][2][2]' index 2 out of bounds\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1040,7 +1039,7 @@ private:
" data[i] = 0;\n" " data[i] = 0;\n"
" }\n" " }\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds: data\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1087,7 +1086,7 @@ private:
" char str[3];\n" " char str[3];\n"
" strcpy(str, \"abc\");\n" " strcpy(str, \"abc\");\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
check("void f(int fd)\n" check("void f(int fd)\n"
"{\n" "{\n"
@ -1101,7 +1100,7 @@ private:
" char str[3];\n" " char str[3];\n"
" read(fd, str, 4);\n" " read(fd, str, 4);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
check("void f(int fd)\n" check("void f(int fd)\n"
"{\n" "{\n"
@ -1115,7 +1114,7 @@ private:
" char str[3];\n" " char str[3];\n"
" write(fd, str, 4);\n" " write(fd, str, 4);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1136,7 +1135,7 @@ private:
" char str[3];\n" " char str[3];\n"
" fgets(str, 4, stdin);\n" " fgets(str, 4, stdin);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
// fread // fread
check("void f(FILE* fd)\n" check("void f(FILE* fd)\n"
@ -1144,7 +1143,7 @@ private:
"char str[3];\n" "char str[3];\n"
"fread(str,sizeof(char),4,fd);\n" "fread(str,sizeof(char),4,fd);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
// fread // fread
check("void f(FILE* fd)\n" check("void f(FILE* fd)\n"
@ -1169,7 +1168,7 @@ private:
"char str[3];\n" "char str[3];\n"
"fwrite(str,sizeof(char),4,fd);\n" "fwrite(str,sizeof(char),4,fd);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
check("void f(FILE* fd)\n" check("void f(FILE* fd)\n"
"{\n" "{\n"
@ -1215,7 +1214,7 @@ private:
" for (i = 0; i <= 10; ++i)\n" " for (i = 0; i <= 10; ++i)\n"
" a[i] = 0;\n" " a[i] = 0;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Buffer access out-of-bounds: a\n", errout.str());
} }
@ -1227,7 +1226,7 @@ private:
" for (int i = 0; i < 8; ++i)\n" " for (int i = 0; i < 8; ++i)\n"
" p[i] = 0;\n" " p[i] = 0;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds: p\n", errout.str());
// No false positive // No false positive
check("void foo(int x, int y)\n" check("void foo(int x, int y)\n"
@ -1248,8 +1247,8 @@ private:
" char s[3];\n" " char s[3];\n"
" f1(s,3);\n" " f1(s,3);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:3]: (possible error) Buffer access out-of-bounds\n", errout.str()); //ASSERT_EQUALS("[test.cpp:3]: (possible error) Buffer access out-of-bounds\n", errout.str());
TODO_ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f1(char *s,int size)\n" check("void f1(char *s,int size)\n"
"{\n" "{\n"
@ -1282,14 +1281,14 @@ private:
" strcat(n, \"abc\");\n" " strcat(n, \"abc\");\n"
" strcat(n, \"def\");\n" " strcat(n, \"def\");\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds: n\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char n[5];\n" " char n[5];\n"
" strcat(strcat(n, \"abc\"), \"def\");\n" " strcat(strcat(n, \"abc\"), \"def\");\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: n\n", errout.str());
} }
void buffer_overrun_7() void buffer_overrun_7()
@ -1570,21 +1569,21 @@ private:
" char str[5];\n" " char str[5];\n"
" memset(str, 0, 10);\n" " memset(str, 0, 10);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: str\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[5], b[50];\n" " char a[5], b[50];\n"
" memcpy(a, b, 10);\n" " memcpy(a, b, 10);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: a\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char a[5], b[50];\n" " char a[5], b[50];\n"
" memmove(a, b, 10);\n" " memmove(a, b, 10);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: a\n", errout.str());
// When this TODO assertion works, ticket #909 can probably be closed // When this TODO assertion works, ticket #909 can probably be closed
check("void f()\n" check("void f()\n"
@ -1864,7 +1863,7 @@ private:
" strcpy(a,\"hello\");\n" " strcpy(a,\"hello\");\n"
" strncpy(c,a,sizeof(c)+1);\n" " strncpy(c,a,sizeof(c)+1);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: c\n", errout.str());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
@ -1878,7 +1877,7 @@ private:
" char c[6];\n" " char c[6];\n"
" strncpy(c,\"hello!\",sizeof(c)+1);\n" " strncpy(c,\"hello!\",sizeof(c)+1);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: c\n", errout.str());
check("struct AB { char a[10]; };\n" check("struct AB { char a[10]; };\n"
"void foo(AB *ab)\n" "void foo(AB *ab)\n"