malloc-interprocedural.c revision c20c7275c351f362b42915901d308ac66b8b71d1
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 5typedef __typeof(sizeof(int)) size_t; 6void *malloc(size_t); 7void *valloc(size_t); 8void free(void *); 9void *realloc(void *ptr, size_t size); 10void *reallocf(void *ptr, size_t size); 11void *calloc(size_t nmemb, size_t size); 12 13void exit(int) __attribute__ ((__noreturn__)); 14void *memcpy(void * restrict s1, const void * restrict s2, size_t n); 15size_t strlen(const char *); 16 17static void my_malloc1(void **d, size_t size) { 18 *d = malloc(size); 19} 20 21static 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 29static void my_free1(void *p) { 30 free(p); 31} 32 33static 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 38static void test11() { 39 void *data = 0; 40 my_malloc1(&data, 4); 41 my_free1(data); 42} 43 44static 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 51static void test3() { 52 void *data = my_malloc2(1, 4); 53 free(data); 54 data = my_malloc2(1, 4); 55 free(data); 56} 57 58int 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 66void 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. 73void test5() { 74 int *data; 75 my_free1((int*)data); 76} 77 78static char *reshape(char *in) { 79 return 0; 80} 81 82void 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;' 89void fooWithEmptyReturn(int x) { 90 if (x) 91 return; 92 x++; 93 return; 94} 95 96int 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> 106char *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 125void 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