updated extracttests.py. fix syntax errors in test cases.

This commit is contained in:
Daniel Marjamäki 2021-05-13 20:21:02 +02:00
parent 7ba9e37296
commit d549770b5b
9 changed files with 329 additions and 186 deletions

View File

@ -2324,6 +2324,21 @@ const Variable *getLHSVariable(const Token *tok)
return getLHSVariableRecursive(tok->astOperand1());
}
const Token* findAllocFuncCallToken(const Token *expr, const Library &library)
{
if (!expr)
return nullptr;
if (Token::Match(expr, "[+-]")) {
const Token *tok1 = findAllocFuncCallToken(expr->astOperand1(), library);
return tok1 ? tok1 : findAllocFuncCallToken(expr->astOperand2(), library);
}
if (expr->isCast())
return findAllocFuncCallToken(expr->astOperand2() ? expr->astOperand2() : expr->astOperand1(), library);
if (Token::Match(expr->previous(), "%name% (") && library.getAllocFuncInfo(expr->astOperand1()))
return expr->astOperand1();
return (Token::simpleMatch(expr, "new") && expr->astOperand1()) ? expr : nullptr;
}
static bool nonLocal(const Variable* var, bool deref)
{
return !var || (!var->isLocal() && !var->isArgument()) || (deref && var->isArgument() && var->isPointer()) || var->isStatic() || var->isReference() || var->isExtern();

View File

@ -281,6 +281,9 @@ const Variable *getLHSVariable(const Token *tok);
std::vector<const Variable*> getLHSVariables(const Token* tok);
/** Find a allocation function call in expression, so result of expression is allocated memory/resource. */
const Token* findAllocFuncCallToken(const Token *expr, const Library &library);
bool isScopeBracket(const Token* tok);
bool isNullOperand(const Token *expr);

View File

@ -171,9 +171,12 @@ void CheckUninitVar::checkScope(const Scope* scope, const std::set<std::string>
if (arg.declarationId() && Token::Match(arg.typeStartToken(), "%type% * %name% [,)]")) {
// Treat the pointer as initialized until it is assigned by malloc
for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
if (!Token::Match(tok, "[;{}] %varid% = %name% (", arg.declarationId()))
if (!Token::Match(tok, "[;{}] %varid% =", arg.declarationId()))
continue;
const Library::AllocFunc *allocFunc = mSettings->library.getAllocFuncInfo(tok->tokAt(3));
const Token *allocFuncCallToken = findAllocFuncCallToken(tok->tokAt(2)->astOperand2(), mSettings->library);
if (!allocFuncCallToken)
continue;
const Library::AllocFunc *allocFunc = mSettings->library.getAllocFuncInfo(allocFuncCallToken);
if (!allocFunc || allocFunc->initData)
continue;

View File

@ -938,11 +938,14 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
}
// Consider allocating memory separately because allocating/freeing alone does not constitute using the variable
else if (var && var->mType == Variables::pointer &&
Token::Match(start, "%name% = new|malloc|calloc|kmalloc|kzalloc|kcalloc|strdup|strndup|vmalloc|g_new0|g_try_new|g_new|g_malloc|g_malloc0|g_try_malloc|g_try_malloc0|g_strdup|g_strndup|g_strdup_printf")) {
Token::Match(start, "%name% =") &&
findAllocFuncCallToken(start->next()->astOperand2(), mSettings->library)) {
bool allocate = true;
if (start->strAt(2) == "new") {
const Token *type = start->tokAt(3);
const Token *allocFuncCallToken = findAllocFuncCallToken(start->next()->astOperand2(), mSettings->library);
if (allocFuncCallToken->str() == "new") {
const Token *type = allocFuncCallToken->next();
// skip nothrow
if (mTokenizer->isCPP() && (Token::simpleMatch(type, "( nothrow )") ||

View File

@ -1013,6 +1013,7 @@ private:
void array_index_30() {
// ticket #2086 - unknown type
// extracttests.start: typedef unsigned char UINT8;
check("void f() {\n"
" UINT8 x[2];\n"
" x[5] = 0;\n"
@ -1245,7 +1246,7 @@ private:
check("void f()\n"
"{\n"
" char *p; p = malloc(10);\n"
" char *p; p = (char *)malloc(10);\n"
" p[10] = 7;\n"
" free(p);\n"
"}");
@ -1253,7 +1254,7 @@ private:
check("void f()\n"
"{\n"
" char *p; p = malloc(10);\n"
" char *p; p = (char *)malloc(10);\n"
" p[0] = 0;\n"
" p[9] = 9;\n"
" free(p);\n"
@ -1880,6 +1881,8 @@ private:
}
void array_index_for_andand_oror() { // #3907 - using && or ||
// extracttests.start: volatile int y;
check("void f() {\n"
" char data[2];\n"
" int x;\n"
@ -1930,10 +1933,11 @@ private:
"}", true);
ASSERT_EQUALS("", errout.str());
// extracttests.start: int maybe();
check("void f() {\n"
" int a[2];\n"
" for (int i = 0; i < 2; ++i) {\n"
" if (somecondition) {\n"
" if (maybe()) {\n"
" continue;\n"
" }\n"
" a[i - 1] = 0;\n"
@ -1967,9 +1971,10 @@ private:
ASSERT_EQUALS("", errout.str());
// Ticket #3893 - start value out of bounds
// extracttests.start: int maybe(); int dostuff();
check("void f() {\n"
" int a[10];\n"
" for (int i = 10; somecondition; dosomething) {\n"
" for (int i = 10; maybe(); dostuff()) {\n"
" a[i] = 0;\n"
" }\n"
"}");
@ -2748,21 +2753,21 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one.\n", errout.str());
check("void f(float a[10][20]);\n"
check("void f(float a[10][3]);\n"
"void g() {\n"
" float a[2][3];\n"
" f(a);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one.\n", errout.str());
check("void f(char a[20]);\n"
check("void f(int a[20]);\n"
"void g() {\n"
" int a[2];\n"
" f(a);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) The array 'a' is too small, the function 'f' expects a bigger one.\n", errout.str());
check("void f(char a[20]);\n"
check("void f(int a[20]);\n"
"void g() {\n"
" int a[5];\n"
" f(a);\n"
@ -2791,7 +2796,7 @@ private:
void possible_buffer_overrun_1() { // #3035
check("void foo() {\n"
" char * data = alloca(50);\n"
" char * data = (char *)alloca(50);\n"
" char src[100];\n"
" memset(src, 'C', 99);\n"
" src[99] = '\\0';\n"
@ -2800,7 +2805,7 @@ private:
ASSERT_EQUALS("[test.cpp:6]: (warning) Possible buffer overflow if strlen(src) is larger than sizeof(data)-strlen(data).\n", errout.str());
check("void foo() {\n"
" char * data = alloca(100);\n"
" char * data = (char *)alloca(100);\n"
" char src[100];\n"
" memset(src, 'C', 99);\n"
" src[99] = '\\0';\n"
@ -2809,19 +2814,19 @@ private:
ASSERT_EQUALS("", errout.str());
check("void foo(char src[100]) {\n"
" char * data = alloca(50);\n"
" char * data = (char *)alloca(50);\n"
" strcat(data, src);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Possible buffer overflow if strlen(src) is larger than sizeof(data)-strlen(data).\n", errout.str());
check("void foo(char src[100]) {\n"
" char * data = alloca(100);\n"
" char * data = (char *)alloca(100);\n"
" strcat(data, src);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" char * data = alloca(50);\n"
" char * data = (char *)alloca(50);\n"
" char src[100];\n"
" memset(src, 'C', 99);\n"
" src[99] = '\\0';\n"
@ -2830,7 +2835,7 @@ private:
ASSERT_EQUALS("[test.cpp:6]: (warning) Possible buffer overflow if strlen(src) is larger than or equal to sizeof(data).\n", errout.str());
check("void foo() {\n"
" char * data = alloca(100);\n"
" char * data = (char *)alloca(100);\n"
" char src[100];\n"
" memset(src, 'C', 99);\n"
" src[99] = '\\0';\n"
@ -2839,13 +2844,13 @@ private:
ASSERT_EQUALS("", errout.str());
check("void foo(char src[100]) {\n"
" char * data = alloca(50);\n"
" char * data = (char *)alloca(50);\n"
" strcpy(data, src);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Possible buffer overflow if strlen(src) is larger than or equal to sizeof(data).\n", errout.str());
check("void foo(char src[100]) {\n"
" char * data = alloca(100);\n"
" char * data = (char *)alloca(100);\n"
" strcpy(data, src);\n"
"}");
ASSERT_EQUALS("", errout.str());
@ -2905,13 +2910,15 @@ private:
}
void pointer_out_of_bounds_1() {
// extracttests.start: void dostuff(char *);
check("void f() {\n"
" char a[10];\n"
" char *p = a + 100;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'a+100' is out of bounds.\n", errout.str());
check("void f() {\n"
check("char *f() {\n"
" char a[10];\n"
" return a + 100;\n"
"}");
@ -2983,7 +2990,7 @@ private:
void pointer_out_of_bounds_3() {
check("struct S { int a[10]; };\n"
"void f(struct S *s) {\n"
" char *p = s->a + 100;\n"
" int *p = s->a + 100;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 's->a+100' is out of bounds.\n", errout.str());
}
@ -3012,7 +3019,9 @@ private:
void pointer_out_of_bounds_sub() {
check("void f() {\n"
// extracttests.start: void dostuff(char *);
check("char *f() {\n"
" char x[10];\n"
" return x-1;\n"
"}");
@ -3129,7 +3138,7 @@ private:
// ticket #1670 - false negative when using return
check("char f()\n"
"{\n"
" char *s; s = new int[10];\n"
" int *s; s = new int[10];\n"
" return s[10];\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds.\n", errout.str());
@ -3177,9 +3186,9 @@ private:
check("void foo()\n"
"{\n"
" enum E { };\n"
" enum E { ZERO };\n"
" E *e; e = new E[10];\n"
" e[10] = 0;\n"
" e[10] = ZERO;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'e[10]' accessed at index 10, which is out of bounds.\n", errout.str());
}
@ -3188,23 +3197,23 @@ private:
void alloc_malloc() {
check("void foo()\n"
"{\n"
" char *s; s = malloc(10);\n"
" char *s; s = (char *)malloc(10);\n"
" s[10] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds.\n", errout.str());
// ticket #842
check("void f() {\n"
" int *tab4 = malloc(20 * sizeof(int));\n"
" int *tab4 = (int *)malloc(20 * sizeof(int));\n"
" tab4[20] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds.\n", errout.str());
// ticket #1478
check("void foo() {\n"
" char *p = malloc(10);\n"
" char *p = (char *)malloc(10);\n"
" free(p);\n"
" p = malloc(10);\n"
" p = (char *)malloc(10);\n"
" p[10] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'p[10]' accessed at index 10, which is out of bounds.\n", errout.str());
@ -3212,7 +3221,7 @@ private:
// ticket #1134
check("void f() {\n"
" int *x, i;\n"
" x = malloc(10 * sizeof(int));\n"
" x = (int *)malloc(10 * sizeof(int));\n"
" x[10] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'x[10]' accessed at index 10, which is out of bounds.\n", errout.str());
@ -3238,22 +3247,22 @@ private:
check("void f() {\n"
" enum E { Size = 20 };\n"
" E *tab4 = malloc(Size * 4);\n"
" tab4[Size] = 0;\n"
" E *tab4 = (E *)malloc(Size * 4);\n"
" tab4[Size] = Size;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds.\n", errout.str());
check("void f() {\n"
" enum E { Size = 20 };\n"
" E *tab4 = malloc(4 * Size);\n"
" tab4[Size] = 0;\n"
" E *tab4 = (E *)malloc(4 * Size);\n"
" tab4[Size] = Size;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds.\n", errout.str());
check("void f() {\n"
" enum E { };\n"
" E *tab4 = malloc(20 * sizeof(E));\n"
" tab4[20] = 0;\n"
" enum E { ZERO };\n"
" E *tab4 = (E *)malloc(20 * sizeof(E));\n"
" tab4[20] = ZERO;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'tab4[20]' accessed at index 20, which is out of bounds.\n", errout.str());
@ -3301,7 +3310,7 @@ private:
void alloc_alloca() {
check("void foo()\n"
"{\n"
" char *s = alloca(10);\n"
" char *s = (char *)alloca(10);\n"
" s[10] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 's[10]' accessed at index 10, which is out of bounds.\n", errout.str());
@ -3378,6 +3387,9 @@ private:
ASSERT_EQUALS(26, CheckBufferOverrun::countSprintfLength("str%-6s%08ld%08ld", multipleParams));
}
*/
// extracttests.disable
void minsize_argvalue() {
Settings settings;
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
@ -3717,6 +3729,8 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds: c\n", errout.str());
}
// extracttests.enable
void unknownType() {
check("void f()\n"
"{\n"
@ -3770,7 +3784,7 @@ private:
" char baz[100];\n"
" strncpy(baz, bar, 100);\n"
" bar[99] = 0;\n"
" return baz;\n"
" return strdup(baz);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) The buffer 'baz' may not be null-terminated after the call to strncpy().\n", errout.str());
}
@ -4095,20 +4109,20 @@ private:
ASSERT_EQUALS("", errout.str());
check("void f(char *a) {\n"
" char *b = malloc(strlen(a));\n"
" char *b = (char *)malloc(strlen(a));\n"
" b = realloc(b, 10000);\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(char *a) {\n"
" char *b = malloc(strlen(a));\n"
" char *b = (char *)malloc(strlen(a));\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
check("void f(char *a) {\n"
" char *b = malloc(strlen(a));\n"
" char *b = (char *)malloc(strlen(a));\n"
" {\n"
" strcpy(b, a);\n"
" }\n"
@ -4116,25 +4130,25 @@ private:
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer is accessed out of bounds.\n", errout.str());
check("void f(char *a) {\n"
" char *b = malloc(strlen(a) + 1);\n"
" char *b = (char *)malloc(strlen(a) + 1);\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(char *a, char *c) {\n"
" char *b = realloc(c, strlen(a));\n"
" char *b = (char *)realloc(c, strlen(a));\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
check("void f(char *a, char *c) {\n"
" char *b = realloc(c, strlen(a) + 1);\n"
" char *b = (char *)realloc(c, strlen(a) + 1);\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(char *a) {\n"
" char *b = malloc(strlen(a));\n"
" char *b = (char *)malloc(strlen(a));\n"
" strcpy(b, a);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer is accessed out of bounds.\n", errout.str());
@ -4144,7 +4158,7 @@ private:
check("class A {\n"
"private:\n"
" struct X { char buf[10]; };\n"
"}\n"
"};\n"
"\n"
"void f()\n"
"{\n"
@ -4156,7 +4170,7 @@ private:
check("class A {\n"
"public:\n"
" struct X { char buf[10]; };\n"
"}\n"
"};\n"
"\n"
"void f()\n"
"{\n"
@ -4173,6 +4187,8 @@ private:
}
void arrayIndexThenCheck() {
// extracttests.start: volatile int y;
check("void f(const char s[]) {\n"
" if (s[i] == 'x' && i < y) {\n"
" }"
@ -4203,12 +4219,14 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str());
// extracttests.start: int elen;
check("void f(char* e, int y) {\n"
" if (e[y] == '/' && elen > y + 1 && e[y + 1] == '?') {\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: int foo(int); int func(int);
check("void f(const int a[], unsigned i) {\n"
" if(a[i] < func(i) && i <= 42) {\n"
" }\n"
@ -4232,6 +4250,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: extern int buf[];
check("void f(int i) {\n" // ?:
" if ((i < 10 ? buf[i] : 1) && (i < 5 ? buf[i] : 5)){}\n"
"}");
@ -4262,15 +4281,7 @@ private:
check("void f()\n"
"{\n"
" int *a;\n"
" a = new int[-1];\n"
" delete [] a;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size is negative.\n", errout.str());
check("void f()\n"
"{\n"
" int *a;\n"
" a = malloc( -10 );\n"
" a = (int *)malloc( -10 );\n"
" free(a);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size is negative.\n", errout.str());
@ -4278,7 +4289,7 @@ private:
check("void f()\n"
"{\n"
" int *a;\n"
" a = malloc( -10);\n"
" a = (int *)malloc( -10);\n"
" free(a);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size is negative.\n", errout.str());
@ -4286,7 +4297,7 @@ private:
check("void f()\n"
"{\n"
" int *a;\n"
" a = alloca( -10 );\n"
" a = (int *)alloca( -10 );\n"
" free(a);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size is negative.\n", errout.str());
@ -4310,7 +4321,7 @@ private:
void pointerAddition1() {
check("void f() {\n"
" char arr[10];\n"
" p = arr + 20;\n"
" char *p = arr + 20;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 'arr+20' is out of bounds.\n", errout.str());
}

View File

@ -191,7 +191,8 @@ private:
void nullpointerAfterLoop() {
check("int foo(const Token *tok)\n"
// extracttests.start: struct Token { const Token *next() const; std::string str() const; };
check("void foo(const Token *tok)\n"
"{\n"
" while (tok);\n"
" tok = tok->next();\n"
@ -363,6 +364,8 @@ private:
// This is checked by this function:
// CheckOther::nullPointerStructByDeRefAndChec
void structDerefAndCheck() {
// extracttests.start: struct ABC { int a; int b; int x; };
// errors..
check("void foo(struct ABC *abc)\n"
"{\n"
@ -622,6 +625,8 @@ private:
// Dereferencing a pointer and then checking if it is null
void pointerDerefAndCheck() {
// extracttests.start: void bar(int);
// errors..
check("void foo(int *p)\n"
"{\n"
@ -992,14 +997,14 @@ private:
"", errout.str());
check("static void foo() {\n"
" int &r = *0;\n"
" int &r = *(int*)0;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference: (int*)0\n", errout.str());
check("static void foo(int x) {\n"
" int y = 5 + *0;\n"
" int y = 5 + *(int*)0;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference: (int*)0\n", errout.str());
{
const char code[] = "static void foo() {\n"
@ -1012,9 +1017,9 @@ private:
}
check("static void foo() {\n"
" std::cout << *0;"
" std::cout << *(int*)0;"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference: (int*)0\n", errout.str());
check("void f()\n"
"{\n"
@ -1027,9 +1032,9 @@ private:
ASSERT_EQUALS("[test.cpp:7]: (error) Null pointer dereference: c\n", errout.str());
check("static void foo() {\n"
" if (3 > *0);\n"
" if (3 > *(int*)0);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (error) Null pointer dereference: (int*)0\n", errout.str());
// no false positive..
check("static void foo()\n"
@ -1218,12 +1223,13 @@ private:
"", errout.str());
// #2231 - error if assignment in loop is not used
// extracttests.start: int y[20];
check("void f() {\n"
" char *p = 0;\n"
"\n"
" for (int x = 0; x < 3; ++x) {\n"
" if (y[x] == 0) {\n"
" p = malloc(10);\n"
" p = (char *)malloc(10);\n"
" break;\n"
" }\n"
" }\n"
@ -1252,6 +1258,7 @@ private:
}
void nullpointer10() {
// extracttests.start: struct my_type { int x; };
check("void foo()\n"
"{\n"
" struct my_type* p = 0;\n"
@ -1261,6 +1268,8 @@ private:
}
void nullpointer11() { // ticket #2812
// extracttests.start: struct my_type { int x; };
check("int foo()\n"
"{\n"
" struct my_type* p;\n"
@ -2184,7 +2193,7 @@ private:
" const Token* next() const;\n"
" int varId() const;\n"
"};\n"
"int f(const Token *first, const Token* second) const {\n"
"int f(const Token *first, const Token* second) {\n"
" first = first->nextArgument();\n"
" if (first)\n"
" first = first->next();\n"
@ -2203,8 +2212,9 @@ private:
" const Token* nextArgument() const;\n"
" const Token* next() const;\n"
" int varId() const;\n"
" void str() const;"
"};\n"
"int f(const Token *first) const {\n"
"void f(const Token *first) {\n"
" first = first->nextArgument();\n"
" if (first)\n"
" first = first->next();\n"
@ -2246,6 +2256,7 @@ private:
}
void nullpointerSwitch() { // #2626
// extracttests.start: char *do_something();
check("char *f(int x) {\n"
" char *p = do_something();\n"
" switch (x) {\n"
@ -2667,7 +2678,7 @@ private:
// Test CheckNullPointer::nullConstantDereference
void nullConstantDereference() {
check("void f() {\n"
check("int f() {\n"
" int* p = 0;\n"
" return p[4];\n"
"}");
@ -2836,9 +2847,10 @@ private:
}
void nullpointer_in_return() {
// extracttests.start: int maybe(); int *g();
check("int foo() {\n"
" int* iVal = 0;\n"
" if(g()) iVal = g();\n"
" if(maybe()) iVal = g();\n"
" return iVal[0];\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (warning) Possible null pointer dereference: iVal\n", errout.str());
@ -3130,6 +3142,8 @@ private:
}
void nullpointerSmartPointer() {
// extracttests.start: void dostuff(int);
check("struct Fred { int x; };\n"
"void f(std::shared_ptr<Fred> p) {\n"
" if (p) {}\n"
@ -3190,7 +3204,7 @@ private:
check("struct Fred { int x; };\n"
"void f(std::shared_ptr<Fred> p) {\n"
" p.release();\n"
" p.reset();\n"
" dostuff(p->x);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference: p\n", errout.str());
@ -3547,7 +3561,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
check("void foo(int *p = 0) {\n"
check("void foo(int x, int *p = 0) {\n"
" int var1 = x ? *p : 5;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Possible null pointer dereference if the default parameter value is used: p\n", errout.str());
@ -3582,7 +3596,7 @@ private:
void subtract() {
check("void foo(char *s) {\n"
" p = s - 20;\n"
" char *p = s - 20;\n"
"}\n"
"void bar() { foo(0); }");
ASSERT_EQUALS("[test.cpp:2]: (error) Overflow in pointer arithmetic, NULL pointer is subtracted.\n",
@ -3590,7 +3604,7 @@ private:
check("void foo(char *s) {\n"
" if (!s) {}\n"
" p = s - 20;\n"
" char *p = s - 20;\n"
"}");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!s' is redundant or there is overflow in pointer subtraction.\n", errout.str());

View File

@ -113,6 +113,8 @@ private:
}
void uninitvar1() {
// extracttests.start: int b; int c;
// Ticket #2207 - False negative
checkUninitVar("void foo() {\n"
" int a;\n"
@ -127,11 +129,13 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
// Ticket #6455 - some compilers allow const variables to be uninitialized
// extracttests.disable
checkUninitVar("void foo() {\n"
" const int a;\n"
" b = c - a;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
// extracttests.enable
checkUninitVar("void foo() {\n"
" int *p;\n"
@ -153,6 +157,7 @@ private:
ASSERT_EQUALS("", errout.str());
// dereferencing uninitialized pointer..
// extracttests.start: struct Foo { void abcd(); };
checkUninitVar("static void foo()\n"
"{\n"
" Foo *p;\n"
@ -160,6 +165,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
// extracttests.start: template<class T> struct Foo { void abcd(); };
checkUninitVar("static void foo()\n"
"{\n"
" Foo<int> *p;\n"
@ -167,6 +173,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
// extracttests.start: struct Foo { void* a; };
checkUninitVar("void f(Foo *p)\n"
"{\n"
" int a;\n"
@ -257,6 +264,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: void bar(int);
checkUninitVar("void f()\n"
"{\n"
" int a;\n"
@ -285,7 +293,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: i\n", errout.str());
checkUninitVar("static int foo(int x)\n"
checkUninitVar("static void foo(int x)\n"
"{\n"
" int i;\n"
" if (x)\n"
@ -317,7 +325,7 @@ private:
ASSERT_EQUALS("", errout.str());
// Ticket #3597
checkUninitVar("int f() {\n"
checkUninitVar("void f() {\n"
" int a;\n"
" int b = 1;\n"
" (b += a) = 1;\n"
@ -345,6 +353,7 @@ private:
ASSERT_EQUALS("", errout.str());
// Unknown types
// extracttests.disable
{
checkUninitVar("void a()\n"
"{\n"
@ -369,6 +378,7 @@ private:
"test.c", false);
ASSERT_EQUALS("", errout.str());
}
// extracttests.enable
checkUninitVar("void a()\n"
"{\n"
@ -730,6 +740,8 @@ private:
}
void uninitvar_warn_once() {
// extracttests.start: int a; int b;
checkUninitVar("void f() {\n"
" int x;\n"
" a = x;\n"
@ -817,6 +829,8 @@ private:
}
void uninitvar_bitop() {
// extracttests.start: int a; int c;
checkUninitVar("void foo() {\n"
" int b;\n"
" c = a | b;\n"
@ -832,7 +846,8 @@ private:
// if..
void uninitvar_if() {
checkUninitVar("static void foo()\n"
// extracttests.start: struct Foo { void abcd(); };
checkUninitVar("static void foo(int x)\n"
"{\n"
" Foo *p;\n"
" if (x)\n"
@ -1148,6 +1163,7 @@ private:
// handling for/while loops..
void uninitvar_loops() {
// for..
// extracttests.start: void b(int);
checkUninitVar("void f()\n"
"{\n"
" for (int i = 0; i < 4; ++i) {\n"
@ -1211,7 +1227,8 @@ private:
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void f(int x) {\n"
// extracttests.start: struct PoolItem { bool operator!=(const PoolItem&) const; };
checkUninitVar("void f(int x, const PoolItem& rPool) {\n"
" const PoolItem* pItem;\n"
" while (x > 0) {\n"
" if (*pItem != rPool)\n"
@ -1257,6 +1274,7 @@ private:
ASSERT_EQUALS("", errout.str());
// #10273 - assignment in conditional code
// extracttests.start: extern const int PORT_LEARN_DISABLE;
checkUninitVar("void foo() {\n"
" int learn;\n"
" for (int index = 0; index < 10; index++) {\n"
@ -1394,7 +1412,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void f() {\n"
checkUninitVar("void f(int x) {\n"
" char a[10], c;\n"
" c = *(x?a:0);\n"
"}");
@ -1420,7 +1438,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void f() {\n"
checkUninitVar("void f(char *s2) {\n"
" char s[20];\n"
" strcpy(s2, s);\n"
"};");
@ -1614,7 +1632,7 @@ private:
// alloc..
void uninitvar_alloc() {
checkUninitVar("void f() {\n"
" char *s = malloc(100);\n"
" char *s = (char *)malloc(100);\n"
" strcat(s, \"abc\");\n"
"};");
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: s\n", errout.str());
@ -1628,19 +1646,19 @@ private:
checkUninitVar("void f()\n"
"{\n"
" char *p = malloc(64);\n"
" char *p = (char*)malloc(64);\n"
" int x = p[0];\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", "", errout.str());
checkUninitVar("void f() {\n"
" char *p = malloc(64);\n"
" char *p = (char*)malloc(64);\n"
" if (p[0]) { }\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str());
checkUninitVar("void f() {\n"
" char *p = malloc(64);\n"
checkUninitVar("char f() {\n"
" char *p = (char*)malloc(64);\n"
" return p[0];\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str());
@ -1725,7 +1743,7 @@ private:
checkUninitVar("void f()\n"
"{\n"
" char *s = malloc(100);\n"
" char *s = (char*)malloc(100);\n"
" if (!s)\n"
" return;\n"
" char c = *s;\n"
@ -2181,6 +2199,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
// extracttests.start: char str[10];
checkUninitVar("void f() {\n"
" int x;\n"
" str[x] = 0;\n"
@ -2205,12 +2224,13 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVar("int f() {\n"
checkUninitVar("void f() {\n"
" int x;\n"
" x = x;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
// extracttests.start: struct ABC {int a;};
checkUninitVar("void f() {\n"
" struct ABC *abc;\n"
" abc->a = 0;\n"
@ -2813,6 +2833,8 @@ private:
}
void uninitvar_funcptr() {
// extracttests.disable
checkUninitVar("void getLibraryContainer() {\n"
" Reference< XStorageBasedLibraryContainer >(*Factory)(const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&)\n"
" = &DocumentDialogLibraryContainer::create;\n"
@ -2832,6 +2854,8 @@ private:
" rxContainer.set((*Factory)(m_aContext, xDocument));\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: Factory\n", errout.str());
// extracttests.enable
}
void uninitvar_operator() { // Ticket #6463, #6680
@ -2912,10 +2936,10 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str());
checkUninitVar("void a(const char c);\n" // const value => error
checkUninitVar("void a(const char *c);\n" // const value => error
"void b() {\n"
" char c;\n"
" a(*c);\n"
" a(&c);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str());
@ -3014,6 +3038,7 @@ private:
ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: now0\n", errout.str());
// #2775 - uninitialized struct pointer in subfunction
// extracttests.start: struct Fred {int x;};
checkUninitVar("void a(struct Fred *fred) {\n"
" fred->x = 0;\n"
"}\n"
@ -3111,10 +3136,11 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: int y;
checkUninitVar("int f(int x) {\n" // FP with ?:
" int a;\n"
" if (x)\n"
" a = p;\n"
" a = y;\n"
" return x ? 2*a : 0;\n"
"}");
ASSERT_EQUALS("", errout.str());
@ -3122,7 +3148,7 @@ private:
checkUninitVar("int f(int x) {\n"
" int a;\n"
" if (x)\n"
" a = p;\n"
" a = y;\n"
" return y ? 2*a : 3*a;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a\n", errout.str());
@ -3253,7 +3279,7 @@ private:
"}\n", "test.c");
ASSERT_EQUALS("", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" static void f() { }\n"
"};\n"
"void test() {\n"
@ -3261,7 +3287,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" static void f() { }\n"
"};\n"
"void test() {\n"
@ -3269,7 +3295,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" static int v;\n"
"};\n"
"void test() {\n"
@ -3277,7 +3303,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" static int v;\n"
"};\n"
"void test() {\n"
@ -3285,7 +3311,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" void f() { }\n"
"};\n"
"void test() {\n"
@ -3293,7 +3319,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" void f() { }\n"
"};\n"
"void test() {\n"
@ -3301,7 +3327,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" int v;\n"
"};\n"
"void test() {\n"
@ -3309,7 +3335,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: element\n", errout.str());
checkUninitVar("class Element {\n"
checkUninitVar("struct Element {\n"
" int v;\n"
"};\n"
"void test() {\n"
@ -3688,6 +3714,8 @@ private:
}
void uninitvar2_while() {
// extracttests.start: int a;
// for, while
checkUninitVar("void f() {\n"
" int x;\n"
@ -3710,11 +3738,13 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Uninitialized variable: x\n", errout.str());
// extracttests.start: struct Element{Element*Next();};
checkUninitVar("void f() {\n"
" for (Element *ptr3 = ptr3->Next(); ptr3; ptr3 = ptr3->Next()) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Uninitialized variable: ptr3\n", errout.str());
// extracttests.start: int a;
checkUninitVar("void f() {\n"
" int x;\n"
" while (a) {\n"
@ -3785,6 +3815,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: void do_something(int);
checkUninitVar("void f(void) {\n"
" int x;\n"
" for (;;) {\n"
@ -3856,7 +3887,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("int f() {\n"
checkUninitVar("void f() {\n"
" char *p = (char *)malloc(256);\n"
" while(*p && *p == '_')\n"
" p++;\n"
@ -3870,6 +3901,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: int a;
checkUninitVar("void f() {\n" // No FN
" for (int i;;i++)\n"
" a=i;\n"
@ -3942,20 +3974,20 @@ private:
void uninitvar2_malloc() {
checkUninitVar("int f() {\n"
" int *p = malloc(40);\n"
" int *p = (int*)malloc(40);\n"
" return *p;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str());
checkUninitVar("int f() {\n"
" int *p = malloc(40);\n"
" var = *p;\n"
checkUninitVar("void f() {\n"
" int *p = (int*)malloc(40);\n"
" int var = *p;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str());
checkUninitVar("struct AB { int a; int b; };\n"
"int f() {\n"
" struct AB *ab = malloc(sizeof(struct AB));\n"
" struct AB *ab = (AB*)malloc(sizeof(struct AB));\n"
" return ab->a;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: ab\n"
@ -3992,7 +4024,7 @@ private:
// function parameter (treat it as initialized until malloc is used)
checkUninitVar("int f(int *p) {\n"
" if (*p == 1) {}\n" // no error
" p = malloc(256);\n"
" p = (int*)malloc(256);\n"
" return *p;\n" // error
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: p\n", errout.str());
@ -4000,15 +4032,15 @@ private:
checkUninitVar("struct AB { int a; int b; };\n"
"int f(struct AB *ab) {\n"
" if (ab->a == 1) {}\n" // no error
" ab = malloc(sizeof(struct AB));\n"
" ab = (AB*)malloc(sizeof(struct AB));\n"
" return ab->a;\n" // error
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized struct member: ab.a\n", errout.str());
checkUninitVar("struct AB { int a; int b; };\n"
"void do_something(struct AB *ab);\n" // unknown function
"int f() {\n"
" struct AB *ab = malloc(sizeof(struct AB));\n"
"void f() {\n"
" struct AB *ab = (AB*)malloc(sizeof(struct AB));\n"
" do_something(ab);\n"
"}");
ASSERT_EQUALS("", errout.str());
@ -4744,6 +4776,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
// extracttests.start: extern const int SIZE;
checkUninitVar("void f() {\n"
" char a[SIZE+10];\n"
" char c = *a;\n"

View File

@ -1576,6 +1576,7 @@ private:
}
void localvar1() {
// extracttests.disable
functionVariableUsage("void foo()\n"
"{\n"
" int i = 0;\n"
@ -2007,9 +2008,12 @@ private:
" int i = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' is assigned a value that is never used.\n", errout.str());
// extracttests.enable
}
void localvar2() {
// extracttests.start: struct undefined { void f(); };
functionVariableUsage("int foo()\n"
"{\n"
" int i;\n"
@ -2032,6 +2036,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.disable
functionVariableUsage("undefined foo()\n"
"{\n"
" undefined i;\n"
@ -2039,6 +2044,7 @@ private:
"}\n",
"test.c");
ASSERT_EQUALS("[test.c:3]: (style) Variable 'i' is not assigned a value.\n", errout.str());
// extracttests.enable
functionVariableUsage("undefined *foo()\n"
"{\n"
@ -2146,7 +2152,7 @@ private:
}
void localvar3() {
functionVariableUsage("void foo()\n"
functionVariableUsage("void foo(int abc)\n"
"{\n"
" int i;\n"
" if ( abc )\n"
@ -2225,6 +2231,8 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unused variable: i\n", errout.str());
// extracttests.start: struct A {int x;};
functionVariableUsage("void foo()\n"
"{\n"
" A * i;\n"
@ -2384,6 +2392,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str());
// extracttests.start: int f();
functionVariableUsage("void foo()\n"
"{\n"
" int a, b, c;\n"
@ -2527,6 +2536,7 @@ private:
}
void localvar13() { // ticket #1640
// extracttests.start: struct OBJECT { int ySize; };
functionVariableUsage("void foo( OBJECT *obj )\n"
"{\n"
" int x;\n"
@ -2592,7 +2602,7 @@ private:
}
void localvar16() { // ticket #1709
functionVariableUsage("int foo()\n"
functionVariableUsage("void foo()\n"
"{\n"
" char buf[5];\n"
" char *ptr = buf;\n"
@ -2600,7 +2610,7 @@ private:
"}");
// TODO ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'buf' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("int foo()\n"
functionVariableUsage("void foo()\n"
"{\n"
" char buf[5];\n"
" char *ptr = buf - 1;\n"
@ -2609,7 +2619,7 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'buf' is not assigned a value.\n", errout.str());
// #3910
functionVariableUsage("int foo() {\n"
functionVariableUsage("void foo() {\n"
" char buf[5];\n"
" char *data[2];\n"
" data[0] = buf;\n"
@ -2617,7 +2627,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("int foo() {\n"
functionVariableUsage("void foo() {\n"
" char buf1[5];\n"
" char buf2[5];\n"
" char *data[2];\n"
@ -2629,6 +2639,7 @@ private:
}
void localvar17() { // ticket #1720
// extracttests.disable
// Don't crash when checking the code below!
functionVariableUsage("void foo()\n"
"{\n"
@ -2642,6 +2653,7 @@ private:
" line_start = ptr;\n"
"}");
ASSERT_EQUALS("[test.cpp:10]: (style) Variable 'line_start' is assigned a value that is never used.\n", errout.str());
// extracttests.enable
}
void localvar18() { // ticket #1723
@ -3028,11 +3040,13 @@ private:
}
void localvar47() { // #6603
// extracttests.disable
functionVariableUsage("void f() {\n"
" int (SfxUndoManager::*retrieveCount)(bool) const\n"
" = (flag) ? &SfxUndoManager::foo : &SfxUndoManager::bar;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'retrieveCount' is assigned a value that is never used.\n", errout.str());
// extracttests.enable
}
void localvar48() { // #6954
@ -3087,8 +3101,9 @@ private:
}
void localvar51() { // #8128 FN
functionVariableUsage("void foo() {\n"
" const char *tok = var->nameToken();\n"
// extracttests.start: struct Token { const Token* next() const; }; const Token* nameToken();
functionVariableUsage("void foo(const Token *var) {\n"
" const Token *tok = nameToken();\n"
" tok = tok->next();\n" // read+write
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'tok' is assigned a value that is never used.\n", errout.str());
@ -3110,7 +3125,7 @@ private:
}
void localvar53() {
functionVariableUsage("void foo() {\n"
functionVariableUsage("void foo(int a, int loop) {\n"
" bool x = false;\n"
" while (loop) {\n"
" if (a) {\n"
@ -3121,7 +3136,7 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("void foo() {\n"
functionVariableUsage("void foo(int a, int loop) {\n"
" bool x = false;\n"
" while (loop) {\n"
" if (a) {\n"
@ -3202,14 +3217,14 @@ private:
void localvarloops() {
// loops
functionVariableUsage("void fun() {\n"
functionVariableUsage("void fun(int c) {\n"
" int x;\n"
" while (c) { x=10; }\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("void dostuff(int x);\n"
"void fun() {\n"
"void fun(int y, int c) {\n"
" int x = 1;\n"
" while (c) {\n"
" dostuff(x);\n"
@ -3357,7 +3372,7 @@ private:
" {\n"
" int *b = &a;\n"
" }\n"
"}");
"};");
ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'b' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("int a;\n"
@ -3475,6 +3490,7 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: int a[10];
functionVariableUsage("void foo()\n"
"{\n"
" int *b = a;\n"
@ -3601,6 +3617,7 @@ private:
ASSERT_EQUALS(// TODO "[test.cpp:4]: (style) Variable 'a' is assigned a value that is never used.\n"
"[test.cpp:5]: (style) Variable 'c' is assigned a value that is never used.\n", errout.str());
// extracttests.start: int x;
functionVariableUsage("void foo()\n"
"{\n"
" int a[10], * b = a + 10;\n"
@ -3625,6 +3642,7 @@ private:
"}");
// TODO ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'c[1]' is assigned a value that is never used.\n", errout.str());
// extracttests.start: void f(int);
functionVariableUsage("void foo()\n"
"{\n"
" int a[10], * b = a + 10;\n"
@ -3819,6 +3837,7 @@ private:
}
void localvaralias6() { // ticket 1729
// extracttests.start: int a(); void b(const char *);
functionVariableUsage("void foo()\n"
"{\n"
" char buf[8];\n"
@ -3859,7 +3878,7 @@ private:
"}");
// TODO ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'buf' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("void foo()\n"
functionVariableUsage("void foo(char *vdata)\n"
"{\n"
" char buf[8];\n"
" char *srcdata;\n"
@ -4336,6 +4355,7 @@ private:
}
void localvarStruct5() {
// extracttests.disable
functionVariableUsage("int foo() {\n"
" A a;\n"
" return a.i;\n"
@ -4354,6 +4374,7 @@ private:
"}\n",
"test.c");
ASSERT_EQUALS("[test.c:2]: (style) Unused variable: a\n", errout.str());
// extracttests.enable
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
@ -4362,13 +4383,6 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a;\n"
" return a.i;\n"
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a;\n"
@ -4377,14 +4391,6 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'a.i' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a;\n"
" a.i = 0;\n"
" return 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'a.i' is assigned a value that is never used.\n", errout.str());
functionVariableUsage("struct A { int i; };\n"
"int foo() {\n"
" A a = { 0 };\n"
@ -4392,12 +4398,14 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used.\n", errout.str());
// extracttests.disable
functionVariableUsage("class A { int i; };\n"
"int foo() {\n"
" A a = { 0 };\n"
" return 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'a' is assigned a value that is never used.\n", errout.str());
// extracttests.enable
functionVariableUsage("class A { int i; public: A(); { } };\n"
"int foo() {\n"
@ -4474,9 +4482,10 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.start: void dostuff(int*);
functionVariableUsage("struct ARG {\n"
" void *a;\n"
" void *b;\n"
" int a;\n"
" int b;\n"
"};\n"
"\n"
"void fun() {\n"
@ -4533,7 +4542,7 @@ private:
void localvarStruct10() { // #6766
functionVariableUsage("struct S { int x; };\n"
"\n"
"void foo() {\n"
"void foo(const struct S s2) {\n"
" struct S s;\n"
" s.x = 3;\n"
" memcpy (&s, &s2, sizeof (S));\n"
@ -4542,6 +4551,8 @@ private:
}
void localvarStructArray() {
// extracttests.start: struct X {int a;};
// #3633 - detect that struct array is assigned a value
functionVariableUsage("void f() {\n"
" struct X x[10];\n"
@ -4674,14 +4685,16 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
// extracttests.disable
functionVariableUsage("void f() {\n" // unknown class => library configuration is needed
" Fred fred;\n"
" int *a; a = b;\n"
" fred += a;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (information) --check-library: Provide <type-checks><unusedvar> configuration for Fred\n", errout.str());
// extracttests.enable
functionVariableUsage("void f() {\n"
functionVariableUsage("void f(std::pair<int,int> x) {\n"
" std::pair<int,int> fred;\n" // class with library configuration
" fred = x;\n"
"}");
@ -4896,28 +4909,6 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" void* ptr = g_malloc(16);\n"
" g_free(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" void* ptr = kmalloc(16, GFP_KERNEL);\n"
" kfree(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" void* ptr = vmalloc(16, GFP_KERNEL);\n"
" vfree(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"
" char* ptr = new char[16];\n"
@ -4925,6 +4916,8 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
// extracttests.disable
functionVariableUsage("void foo()\n"
"{\n"
" char* ptr = new ( nothrow ) char[16];\n"
@ -4939,6 +4932,8 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
// extracttests.enable
functionVariableUsage("void foo()\n"
"{\n"
" char* ptr = new char;\n"
@ -5009,7 +5004,7 @@ private:
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
" Fred* ptr = malloc(sizeof(Fred));\n"
" Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" free(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
@ -5017,7 +5012,7 @@ private:
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
" Fred* ptr = malloc(sizeof(Fred));\n"
" Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" ptr->i = 0;\n"
" free(ptr);\n"
"}");
@ -5026,7 +5021,7 @@ private:
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
" struct Fred* ptr = malloc(sizeof(Fred));\n"
" struct Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" free(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
@ -5034,7 +5029,7 @@ private:
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
" struct Fred* ptr = malloc(sizeof(Fred));\n"
" struct Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" ptr->i = 0;\n"
" free(ptr);\n"
"}");
@ -5048,6 +5043,8 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
// extracttests.disable
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
@ -5064,6 +5061,8 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
// extracttests.enable
functionVariableUsage("struct Fred { int i; };\n"
"void foo()\n"
"{\n"
@ -5093,7 +5092,7 @@ private:
functionVariableUsage("class Fred { public: int i; };\n"
"void foo()\n"
"{\n"
" Fred* ptr = malloc(sizeof(Fred));\n"
" Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" free(ptr);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'ptr' is allocated memory that is never used.\n", errout.str());
@ -5101,7 +5100,7 @@ private:
functionVariableUsage("class Fred { public: int i; };\n"
"void foo()\n"
"{\n"
" Fred* ptr = malloc(sizeof(Fred));\n"
" Fred* ptr = (Fred*)malloc(sizeof(Fred));\n"
" ptr->i = 0;\n"
" free(ptr);\n"
"}");
@ -5344,6 +5343,8 @@ private:
}
void localVarStd() {
// extracttests.start: struct MyClass {int x;}; std::string foo();
functionVariableUsage("void f() {\n"
" std::string x = foo();\n"
"}");

View File

@ -26,6 +26,43 @@ import sys
import re
def add_includes(code):
includes = (('alloca','alloca.h'),
('NULL','cstddef'),
('size_t','cstddef'),
('free','cstdlib'),
('malloc','cstdlib'),
('realloc','cstdlib'),
('stdin','cstdio'),
('strcat','cstring'),
('strchr','cstring'),
('strcpy','cstring'),
('strlen','cstring'),
('strncat','cstring'),
('strncpy','cstring'),
('std::cout','iostream'),
('std::shared_ptr','memory'),
('std::string','string'),
('std::unique_ptr','memory'))
for i in includes:
if i[0] in code:
include_header = f'#include <{i[1]}>'
if include_header not in code:
code = include_header + '\n' + code
return code
def tweak_expected(expected, start_code):
if start_code is None:
return expected
res = re.match(r'\[([^:\]]+):([0-9]+)\](.*)', expected)
if res is None:
return expected
lines = len(start_code.split('\n'))
return '[%s:%i]%s' % (res.group(1), lines + int(res.group(2)), res.group(3))
class Extract:
"""
@ -48,6 +85,8 @@ class Extract:
testclass = None
functionName = None
code = None
start_code = None
disable = False
fin = open(filename, 'r')
for line in fin:
@ -64,31 +103,47 @@ class Extract:
res = re.match('\\s+void (' + name + ')\\(\\)', line)
if res is not None:
functionName = res.group(1)
start_code = None
elif re.match('\\s+}', line) is not None:
functionName = None
if functionName is None:
# extracttests commands..
res = re.match(r'\s*//\s*extracttests.start:(.*)', line)
if res is not None:
start_code = res.group(1).replace('\\n', '\n')
elif line.find('extracttests.disable') >= 0:
disable = True
elif line.find('extracttests.enable') >= 0:
disable = False
if functionName is None or disable:
continue
# check
res = re.match('\\s+check.*\\(' + string, line)
res = re.match('\\s+' + check_function + '\\(' + string, line)
if res is not None:
code = res.group(1)
if start_code:
code = start_code + '\n' + code
# code..
if code is not None:
res = re.match('\\s+' + string, line)
if res is not None:
code = code + res.group(1)
if res.group(1).find('"') > 0:
code = None
# assert
res = re.match('\\s+ASSERT_EQUALS\\(\\"([^"]*)\\",', line)
if res is not None and code is not None:
code = add_includes(code)
expected = tweak_expected(res.group(1), start_code)
node = {'testclass': testclass,
'functionName': functionName,
'code': code,
'expected': res.group(1)}
'code': code.replace("\\\\", "\\"),
'expected': expected}
self.nodes.append(node)
code = None
@ -165,7 +220,7 @@ def writeHtmlFile(nodes, functionName, filename, errorsOnly):
if len(sys.argv) <= 1 or '--help' in sys.argv:
print('Extract test cases from test file')
print(
'Syntax: extracttests.py [--html=folder] [--xml] [--code=folder] [--onlyTP] path/testfile.cpp')
'Syntax: extracttests.py [--html=folder] [--xml] [--code=folder] [--only-tp] [--check-function=check] path/testfile.cpp')
sys.exit(0)
# parse command line
@ -174,10 +229,11 @@ filename = None
htmldir = None
codedir = None
onlyTP = None
check_function = 'check.*'
for arg in sys.argv[1:]:
if arg == '--xml':
xml = True
elif arg == '--onlyTP':
elif arg == '--only-tp':
onlyTP = True
elif arg.startswith('--html='):
htmldir = arg[7:]
@ -185,6 +241,8 @@ for arg in sys.argv[1:]:
codedir = arg[7:]
elif arg.endswith('.cpp'):
filename = arg
elif arg.startswith('--check-function='):
check_function = arg[17:]
else:
print('Invalid option: ' + arg)
sys.exit(1)
@ -286,6 +344,11 @@ if filename is not None:
errors = open(codedir + 'errors.txt', 'w')
testfile = filename
if testfile.find('/'):
testfile = testfile[testfile.rfind('/'):]
testfile = testfile[:testfile.find('.')]
for node in e.nodes:
if onlyTP and node['expected'] == '':
continue
@ -298,14 +361,11 @@ if filename is not None:
code = code.replace('\\"', '"')
expected = node['expected']
filename = '0000' + str(testnum) + '-'
filename = filename[-4:]
filename += functionName + '.cpp'
filename = '%s-%03i-%s.cpp' % (testfile, testnum, functionName)
# source code
fout = open(codedir + filename, 'w')
fout.write(code)
fout.close()
with open(codedir + filename, 'w') as fout:
fout.write(code)
# write 'expected' to errors.txt
if expected != '':