summaryrefslogtreecommitdiffstats
path: root/test/Analysis/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/malloc.c')
-rw-r--r--test/Analysis/malloc.c228
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
}
OpenPOWER on IntegriCloud