ASSERT_EQUALS("[test.cpp:5:12]: (warning) Using 'sizeof' on array given as function argument returns size of a pointer. [sizeofwithsilentarraypointer]\n",
errout_str());
}
voidsizeofForNumericParameter() {
check("void f() {\n"
" std::cout << sizeof(10) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:18]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter. [sizeofwithnumericparameter]\n", errout_str());
check("void f() {\n"
" std::cout << sizeof(-10) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:18]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter. [sizeofwithnumericparameter]\n", errout_str());
check("void f() {\n"
" std::cout << sizeof 10 << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:18]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter. [sizeofwithnumericparameter]\n", errout_str());
check("void f() {\n"
" std::cout << sizeof -10 << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:18]: (warning) Suspicious usage of 'sizeof' with a numeric constant as parameter. [sizeofwithnumericparameter]\n", errout_str());
}
voidsuspiciousSizeofCalculation() {
check("void f() {\n"
" int* p;\n"
" return sizeof(p)/5;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:10]: (warning, inconclusive) Division of result of sizeof() on pointer type. [divideSizeof]\n", errout_str());
check("void f() {\n"
" unknown p;\n"
" return sizeof(p)/5;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" return sizeof(unknown)/5;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" int p;\n"
" return sizeof(p)/5;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" int* p[5];\n"
" return sizeof(p)/5;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" return sizeof(foo)*sizeof(bar);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:10]: (warning, inconclusive) Multiplying sizeof() with sizeof() indicates a logic error. [multiplySizeof]\n", errout_str());
ASSERT_EQUALS("[test.cpp:2:56]: (warning, inconclusive) Division of result of sizeof() on pointer type. [divideSizeof]\n"
"[test.cpp:2:54]: (warning) Division by result of sizeof(). memmove() expects a size in bytes, did you intend to multiply instead? [sizeofDivisionMemfunc]\n",
errout_str());
check("Foo* allocFoo(int num) {\n"
" return malloc(num / sizeof(Foo));\n"
"}");
ASSERT_EQUALS("[test.cpp:2:23]: (warning) Division by result of sizeof(). malloc() expects a size in bytes, did you intend to multiply instead? [sizeofDivisionMemfunc]\n", errout_str());
" memcpy(b, a, ((sizeof(a) / sizeof(a[0])) - 1) * sizeof(a[0]));\n"
" memcpy(b, a, sizeof(a[0]) * ((sizeof(a) / sizeof(a[0])) - 1));\n"
"}\n");
ASSERT_EQUALS("", errout_str());
}
voidsizeofVoid() {
check("void f() {\n"
" int size = sizeof(void);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:14]: (portability) Behaviour of 'sizeof(void)' is not covered by the ISO C standard. [sizeofVoid]\n", errout_str());
check("void f() {\n"
" void* p;\n"
" int size = sizeof(*p);\n"
"}");
ASSERT_EQUALS("[test.cpp:3:14]: (portability) '*p' is of type 'void', the behaviour of 'sizeof(void)' is not covered by the ISO C standard. [sizeofDereferencedVoidPointer]\n", errout_str());
check("void f() {\n"
" void* p = malloc(10);\n"
" int* p2 = p + 4;\n"
" int* p3 = p - 1;\n"
" int* p4 = 1 + p;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:15]: (portability) 'p' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:4:15]: (portability) 'p' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:5:15]: (portability) 'p' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("void f() {\n"
" void* p1 = malloc(10);\n"
" void* p2 = malloc(5);\n"
" p1--;\n"
" p2++;\n"
"}");
ASSERT_EQUALS("[test.cpp:4:5]: (portability) 'p1' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:5:5]: (portability) 'p2' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("void f() {\n"
" void* p1 = malloc(10);\n"
" void* p2 = malloc(5);\n"
" p1-=4;\n"
" p2+=4;\n"
"}");
ASSERT_EQUALS("[test.cpp:4:5]: (portability) 'p1' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:5:5]: (portability) 'p2' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("void f() {\n"
" void* p = malloc(10);\n"
" int* p2 = &p + 4;\n"
" int* p3 = &p - 1;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" void** p1 = malloc(10);\n"
" p1--;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" void** p1;\n"
" int j = sizeof(*p1);\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" void* p1[5];\n"
" int j = sizeof(*p1);\n"
"}");
ASSERT_EQUALS("", errout_str());
// Calculations on void* with casts
check("void f(void *data) {\n"
" *((unsigned char *)data + 1) = 0;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f(void *data) {\n"
" *((unsigned char *)(data) + 1) = 0;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f(void *data) {\n"
" unsigned char* c = (unsigned char *)(data + 1);\n"
"}");
ASSERT_EQUALS("[test.cpp:2:45]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("void f(void *data) {\n"
" unsigned char* c = (unsigned char *)data++;\n"
" unsigned char* c2 = (unsigned char *)++data;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:43]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:3:40]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("void f(void *data) {\n"
" void* data2 = data + 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:2:22]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
// #4908 (void pointer as a member of a struct/class)
check("struct FOO {\n"
" void *data;\n"
"};\n"
"char f(struct FOO foo) {\n"
" char x = *((char*)(foo.data+1));\n"
" foo.data++;\n"
" return x;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:30]: (portability) 'foo.data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n"
"[test.cpp:6:11]: (portability) 'foo.data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("struct FOO {\n"
" void *data;\n"
"};\n"
"char f(struct FOO foo) {\n"
" char x = *((char*)foo.data+1);\n"
" return x;\n"
"}\n"
"char f2(struct FOO foo) {\n"
" char x = *((char*)((FOO)foo).data + 1);\n"
" return x;\n"
"}\n"
"char f3(struct FOO* foo) {\n"
" char x = *((char*)foo->data + 1);\n"
" return x;\n"
"}\n"
"struct BOO {\n"
" FOO data;\n"
"};\n"
"void f4(struct BOO* boo) {\n"
" char c = *((char*)boo->data.data + 1);\n"
"}");
ASSERT_EQUALS("", errout_str());
check("struct FOO {\n"
" void *data;\n"
"};\n"
"char f(struct FOO* foo) {\n"
" *(foo[1].data + 1) = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:17]: (portability) 'foo[1].data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
check("struct FOO {\n"
" void *data;\n"
"};\n"
"void f2(struct FOO* foo) {\n"
" (foo[0]).data++;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:16]: (portability) '(foo[0]).data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. [arithOperationsOnVoidPointer]\n", errout_str());
// #6050 arithmetic on void**
check("void* array[10];\n"
"void** b = array + 3;");
ASSERT_EQUALS("", errout_str());
}
voidcustomStrncat() {
// Ensure we don't crash on custom-defined strncat, ticket #5875