1 // RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-max-stack-depth=5 -verify %s 2 3 #include "Inputs/system-header-simulator.h" 4 5 typedef __typeof(sizeof(int)) size_t; 6 void *malloc(size_t); 7 void *valloc(size_t); 8 void free(void *); 9 void *realloc(void *ptr, size_t size); 10 void *reallocf(void *ptr, size_t size); 11 void *calloc(size_t nmemb, size_t size); 12 13 void exit(int) __attribute__ ((__noreturn__)); 14 void *memcpy(void * restrict s1, const void * restrict s2, size_t n); 15 size_t strlen(const char *); 16 17 static void my_malloc1(void **d, size_t size) { 18 *d = malloc(size); 19 } 20 21 static void *my_malloc2(int elevel, size_t size) { 22 void *data; 23 data = malloc(size); 24 if (data == 0) 25 exit(0); 26 return data; 27 } 28 29 static void my_free1(void *p) { 30 free(p); 31 } 32 33 static void test1() { 34 void *data = 0; 35 my_malloc1(&data, 4); // expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} 36 } 37 38 static void test11() { 39 void *data = 0; 40 my_malloc1(&data, 4); 41 my_free1(data); 42 } 43 44 static void testUniqueingByallocationSiteInTopLevelFunction() { 45 void *data = my_malloc2(1, 4); 46 data = 0; 47 int x = 5;// expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} 48 data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} 49 } 50 51 static void test3() { 52 void *data = my_malloc2(1, 4); 53 free(data); 54 data = my_malloc2(1, 4); 55 free(data); 56 } 57 58 int test4() { 59 int *data = (int*)my_malloc2(1, 4); 60 my_free1(data); 61 data = (int *)my_malloc2(1, 4); 62 my_free1(data); 63 return *data; // expected-warning {{Use of memory after it is freed}} 64 } 65 66 void test6() { 67 int *data = (int *)my_malloc2(1, 4); 68 my_free1((int*)data); 69 my_free1((int*)data); // expected-warning{{Use of memory after it is freed}} 70 } 71 72 // TODO: We should warn here. 73 void test5() { 74 int *data; 75 my_free1((int*)data); 76 } 77 78 static char *reshape(char *in) { 79 return 0; 80 } 81 82 void testThatRemoveDeadBindingsRunBeforeEachCall() { 83 char *v = malloc(12); 84 v = reshape(v); 85 v = reshape(v);// expected-warning {{Memory is never released; potential leak of memory pointed to by 'v'}} 86 } 87 88 // Test that we keep processing after 'return;' 89 void fooWithEmptyReturn(int x) { 90 if (x) 91 return; 92 x++; 93 return; 94 } 95 96 int uafAndCallsFooWithEmptyReturn() { 97 int *x = (int*)malloc(12); 98 free(x); 99 fooWithEmptyReturn(12); 100 return *x; // expected-warning {{Use of memory after it is freed}} 101 } 102 103 104 // If we inline any of the malloc-family functions, the checker shouldn't also 105 // try to do additional modeling. <rdar://problem/12317671> 106 char *strndup(const char *str, size_t n) { 107 if (!str) 108 return 0; 109 110 // DO NOT FIX. This is to test that we are actually using the inlined 111 // behavior! 112 if (n < 5) 113 return 0; 114 115 size_t length = strlen(str); 116 if (length < n) 117 n = length; 118 119 char *result = malloc(n + 1); 120 memcpy(result, str, n); 121 result[n] = '\0'; 122 return result; 123 } 124 125 void useStrndup(size_t n) { 126 if (n == 0) 127 (void)strndup(0, 20); // no-warning 128 else if (n < 5) 129 (void)strndup("hi there", n); // no-warning 130 else 131 (void)strndup("hi there", n); // expected-warning{{leak}} 132 } 133