diff options
author | Anna Zaks <ganna@apple.com> | 2013-02-07 23:05:47 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2013-02-07 23:05:47 +0000 |
commit | c89ad07d39a435a4069f890417747487f4b3abbf (patch) | |
tree | 802d570dd3c71cb8526b933cdeca91435b61c515 /clang/test/Analysis/malloc.c | |
parent | acdc13cb00591e2ab2b168c7924d7eb57fa4808e (diff) | |
download | bcm5719-llvm-c89ad07d39a435a4069f890417747487f4b3abbf.tar.gz bcm5719-llvm-c89ad07d39a435a4069f890417747487f4b3abbf.zip |
[analyzer] Report bugs when freeing memory with offset pointer
The malloc checker will now catch the case when a previously malloc'ed
region is freed, but the pointer passed to free does not point to the
start of the allocated memory. For example:
int *p1 = malloc(sizeof(int));
p1++;
free(p1); // warn
From the "memory.LeakPtrValChanged enhancement to unix.Malloc" entry
in the list of potential checkers.
A patch by Branden Archer!
llvm-svn: 174678
Diffstat (limited to 'clang/test/Analysis/malloc.c')
-rw-r--r-- | clang/test/Analysis/malloc.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index 9dc17e630fc..29f5aa69ca5 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -1090,4 +1090,104 @@ void testPassToSystemHeaderFunctionIndirectlyStruct() { fakeSystemHeaderCall(&ss); } // missing leak +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()}} +} |