diff options
Diffstat (limited to 'test/Analysis/malloc.c')
-rw-r--r-- | test/Analysis/malloc.c | 228 |
1 files changed, 192 insertions, 36 deletions
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index 68308fd..7790b32 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s -// REQUIRES: LP64 #include "Inputs/system-header-simulator.h" @@ -14,6 +13,7 @@ void *reallocf(void *ptr, size_t size); void *calloc(size_t nmemb, size_t size); char *strdup(const char *s); char *strndup(const char *s, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); void myfoo(int *p); void myfooint(int p); @@ -104,8 +104,8 @@ void reallocSizeZero5() { } void reallocPtrZero1() { - char *r = realloc(0, 12); // expected-warning {{Memory is never released; potential leak of memory pointed to by 'r'}} -} + char *r = realloc(0, 12); +} // expected-warning {{Memory is never released; potential leak of memory pointed to by 'r'}} void reallocPtrZero2() { char *r = realloc(0, 12); @@ -130,12 +130,12 @@ void reallocRadar6337483_1() { void reallocRadar6337483_2() { char *buf = malloc(100); char *buf2 = (char*)realloc(buf, 0x1000000); - if (!buf2) { // expected-warning {{Memory is never released; potential leak}} + if (!buf2) { ; } else { free(buf2); } -} +} // expected-warning {{Memory is never released; potential leak}} void reallocRadar6337483_3() { char * buf = malloc(100); @@ -188,8 +188,8 @@ void reallocfRadar6337483_3() { } void reallocfPtrZero1() { - char *r = reallocf(0, 12); // expected-warning {{Memory is never released; potential leak}} -} + char *r = reallocf(0, 12); +} // expected-warning {{Memory is never released; potential leak}} // This case tests that storing malloc'ed memory to a static variable which is @@ -386,13 +386,13 @@ void mallocBindFreeUse() { void mallocEscapeMalloc() { int *p = malloc(12); myfoo(p); - p = malloc(12); // expected-warning{{Memory is never released; potential leak}} -} + p = malloc(12); +} // expected-warning{{Memory is never released; potential leak}} void mallocMalloc() { int *p = malloc(12); - p = malloc(12); // expected-warning {{Memory is never released; potential leak}} -} + p = malloc(12); +} // expected-warning {{Memory is never released; potential leak}} void mallocFreeMalloc() { int *p = malloc(12); @@ -456,8 +456,8 @@ void mallocFailedOrNotLeak() { void mallocAssignment() { char *p = malloc(12); - p = fooRetPtr(); // expected-warning {{leak}} -} + p = fooRetPtr(); +} // expected-warning {{leak}} int vallocTest() { char *mem = valloc(12); @@ -626,8 +626,8 @@ void mallocAssert(int *g) { void doNotInvalidateWhenPassedToSystemCalls(char *s) { char *p = malloc(12); strlen(p); - strcpy(p, s); // expected-warning {{leak}} -} + strcpy(p, s); +} // expected-warning {{leak}} // Rely on the CString checker evaluation of the strcpy API to convey that the result of strcpy is equal to p. void symbolLostWithStrcpy(char *s) { @@ -673,8 +673,8 @@ int *specialMallocWithStruct() { // Test various allocation/deallocation functions. void testStrdup(const char *s, unsigned validIndex) { char *s2 = strdup(s); - s2[validIndex + 1] = 'b';// expected-warning {{Memory is never released; potential leak}} -} + s2[validIndex + 1] = 'b'; +} // expected-warning {{Memory is never released; potential leak}} int testStrndup(const char *s, unsigned validIndex, unsigned size) { char *s2 = strndup(s, size); @@ -782,10 +782,11 @@ void radar10978247_positive(int myValueSize) { buffer = malloc(myValueSize); // do stuff with the buffer - if (buffer == stackBuffer) // expected-warning {{leak}} + if (buffer == stackBuffer) return; -} - + else + return; // expected-warning {{leak}} +} // <rdar://problem/11269741> Previously this triggered a false positive // because malloc() is known to return uninitialized memory and the binding // of 'o' to 'p->n' was not getting propertly handled. Now we report a leak. @@ -821,8 +822,8 @@ void radar11270219(void) { void radar_11358224_test_double_assign_ints_positive_2() { void *ptr = malloc(16); - ptr = ptr; // expected-warning {{leak}} -} + ptr = ptr; +} // expected-warning {{leak}} // Assume that functions which take a function pointer can free memory even if // they are defined in system headers and take the const pointer to the @@ -836,8 +837,8 @@ void r11160612_1() { // Null is passed as callback. void r11160612_2() { char *x = malloc(12); - const_ptr_and_callback(0, x, 12, 0); // expected-warning {{leak}} -} + const_ptr_and_callback(0, x, 12, 0); +} // expected-warning {{leak}} // Callback is passed to a function defined in a system header. void r11160612_4() { @@ -937,29 +938,33 @@ int cmpHeapAllocationToUnknown() { void localArrayTest() { char *p = (char*)malloc(12); char *ArrayL[12]; - ArrayL[0] = p; // expected-warning {{leak}} -} + ArrayL[0] = p; +} // expected-warning {{leak}} void localStructTest() { StructWithPtr St; StructWithPtr *pSt = &St; - pSt->memP = malloc(12); // expected-warning{{Memory is never released; potential leak}} -} + pSt->memP = malloc(12); +} // expected-warning{{Memory is never released; potential leak}} +#ifdef __INTPTR_TYPE__ // Test double assignment through integers. -static long glob; +typedef __INTPTR_TYPE__ intptr_t; +typedef unsigned __INTPTR_TYPE__ uintptr_t; + +static intptr_t glob; void test_double_assign_ints() { void *ptr = malloc (16); // no-warning - glob = (long)(unsigned long)ptr; + glob = (intptr_t)(uintptr_t)ptr; } void test_double_assign_ints_positive() { void *ptr = malloc(16); - (void*)(long)(unsigned long)ptr; // expected-warning {{unused}} expected-warning {{leak}} -} - + (void*)(intptr_t)(uintptr_t)ptr; // expected-warning {{unused}} +} // expected-warning {{leak}} +#endif void testCGContextNoLeak() { @@ -1032,15 +1037,166 @@ void *test(void *ptr) { return newPtr; } + +char *testLeakWithinReturn(char *str) { + return strdup(strdup(str)); // expected-warning{{leak}} +} + +void passConstPtr(const char * ptr); + +void testPassConstPointer() { + char * string = malloc(sizeof(char)*10); + passConstPtr(string); + return; // expected-warning {{leak}} +} + +void testPassConstPointerIndirectly() { + char *p = malloc(1); + p++; + memcmp(p, p, sizeof(&p)); + return; // expected-warning {{leak}} +} + +void testPassToSystemHeaderFunctionIndirectly() { + int *p = malloc(4); + p++; + fakeSystemHeaderCallInt(p); +} // expected-warning {{leak}} + +void testPassConstPointerIndirectlyStruct() { + struct HasPtr hp; + hp.p = malloc(10); + memcmp(&hp, &hp, sizeof(hp)); + return; // expected-warning {{Memory is never released; potential leak of memory pointed to by 'hp.p'}} +} + +void testPassToSystemHeaderFunctionIndirectlyStruct() { + SomeStruct ss; + ss.p = malloc(1); + fakeSystemHeaderCall(&ss); +} // expected-warning {{Memory is never released; potential leak of memory pointed to by 'ss.p'}} + +int *testOffsetAllocate(size_t size) { + int *memoryBlock = (int *)malloc(size + sizeof(int)); + return &memoryBlock[1]; // no-warning +} + +void testOffsetDeallocate(int *memoryBlock) { + free(&memoryBlock[-1]); // no-warning +} + +void testOffsetOfRegionFreed() { + __int64_t * array = malloc(sizeof(__int64_t)*2); + array += 1; + free(&array[0]); // expected-warning{{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}} +} + +void testOffsetOfRegionFreed2() { + __int64_t *p = malloc(sizeof(__int64_t)*2); + p += 1; + free(p); // expected-warning{{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}} +} + +void testOffsetOfRegionFreed3() { + char *r = malloc(sizeof(char)); + r = r - 10; + free(r); // expected-warning {{Argument to free() is offset by -10 bytes from the start of memory allocated by malloc()}} +} + +void testOffsetOfRegionFreedAfterFunctionCall() { + int *p = malloc(sizeof(int)*2); + p += 1; + myfoo(p); + free(p); // no-warning +} + +void testFixManipulatedPointerBeforeFree() { + int * array = malloc(sizeof(int)*2); + array += 1; + free(&array[-1]); // no-warning +} + +void testFixManipulatedPointerBeforeFree2() { + char *r = malloc(sizeof(char)); + r = r + 10; + free(r-10); // no-warning +} + +void freeOffsetPointerPassedToFunction() { + __int64_t *p = malloc(sizeof(__int64_t)*2); + p[1] = 0; + p += 1; + myfooint(*p); // not passing the pointer, only a value pointed by pointer + free(p); // expected-warning {{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}} +} + +int arbitraryInt(); +void freeUnknownOffsetPointer() { + char *r = malloc(sizeof(char)); + r = r + arbitraryInt(); // unable to reason about what the offset might be + free(r); // no-warning +} + +void testFreeNonMallocPointerWithNoOffset() { + char c; + char *r = &c; + r = r + 10; + free(r-10); // expected-warning {{Argument to free() is the address of the local variable 'c', which is not memory allocated by malloc()}} +} + +void testFreeNonMallocPointerWithOffset() { + char c; + char *r = &c; + free(r+1); // expected-warning {{Argument to free() is the address of the local variable 'c', which is not memory allocated by malloc()}} +} + +void testOffsetZeroDoubleFree() { + int *array = malloc(sizeof(int)*2); + int *p = &array[0]; + free(p); + free(&array[0]); // expected-warning{{Attempt to free released memory}} +} + +void testOffsetPassedToStrlen() { + char * string = malloc(sizeof(char)*10); + string += 1; + int length = strlen(string); // expected-warning {{Memory is never released; potential leak of memory pointed to by 'string'}} +} + +void testOffsetPassedToStrlenThenFree() { + char * string = malloc(sizeof(char)*10); + string += 1; + int length = strlen(string); + free(string); // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}} +} + +void testOffsetPassedAsConst() { + char * string = malloc(sizeof(char)*10); + string += 1; + passConstPtr(string); + free(string); // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}} +} + +char **_vectorSegments; +int _nVectorSegments; + +void poolFreeC(void* s) { + free(s); // no-warning +} +void freeMemory() { + while (_nVectorSegments) { + poolFreeC(_vectorSegments[_nVectorSegments++]); + } +} + // ---------------------------------------------------------------------------- // False negatives. -// TODO: This is another false negative. void testMallocWithParam(int **p) { *p = (int*) malloc(sizeof(int)); - *p = 0; + *p = 0; // FIXME: should warn here } void testMallocWithParam_2(int **p) { - *p = (int*) malloc(sizeof(int)); + *p = (int*) malloc(sizeof(int)); // no-warning } |