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