1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -verify %s |
2 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s |
3 | |
4 | #include "Inputs/system-header-simulator-objc.h" |
5 | #include "Inputs/system-header-simulator-cxx.h" |
6 | |
7 | typedef __typeof__(sizeof(int)) size_t; |
8 | void *malloc(size_t); |
9 | void *realloc(void *ptr, size_t size); |
10 | void *calloc(size_t nmemb, size_t size); |
11 | char *strdup(const char *s); |
12 | void __attribute((ownership_returns(malloc))) *my_malloc(size_t); |
13 | |
14 | void free(void *); |
15 | void __attribute((ownership_takes(malloc, 1))) my_free(void *); |
16 | |
17 | //--------------------------------------------------------------- |
18 | // Test if an allocation function matches deallocation function |
19 | //--------------------------------------------------------------- |
20 | |
21 | //--------------- test malloc family |
22 | void testMalloc1() { |
23 | int *p = (int *)malloc(sizeof(int)); |
24 | delete p; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}} |
25 | } |
26 | |
27 | void testMalloc2() { |
28 | int *p = (int *)malloc(8); |
29 | int *q = (int *)realloc(p, 16); |
30 | delete q; // expected-warning{{Memory allocated by realloc() should be deallocated by free(), not 'delete'}} |
31 | } |
32 | |
33 | void testMalloc3() { |
34 | int *p = (int *)calloc(1, sizeof(int)); |
35 | delete p; // expected-warning{{Memory allocated by calloc() should be deallocated by free(), not 'delete'}} |
36 | } |
37 | |
38 | void testMalloc4(const char *s) { |
39 | char *p = strdup(s); |
40 | delete p; // expected-warning{{Memory allocated by strdup() should be deallocated by free(), not 'delete'}} |
41 | } |
42 | |
43 | void testMalloc5() { |
44 | int *p = (int *)my_malloc(sizeof(int)); |
45 | delete p; // expected-warning{{Memory allocated by my_malloc() should be deallocated by free(), not 'delete'}} |
46 | } |
47 | |
48 | void testMalloc6() { |
49 | int *p = (int *)malloc(sizeof(int)); |
50 | operator delete(p); // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not operator delete}} |
51 | } |
52 | |
53 | void testMalloc7() { |
54 | int *p = (int *)malloc(sizeof(int)); |
55 | delete[] p; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete[]'}} |
56 | } |
57 | |
58 | void testMalloc8() { |
59 | int *p = (int *)malloc(sizeof(int)); |
60 | operator delete[](p); // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not operator delete[]}} |
61 | } |
62 | |
63 | void testAlloca() { |
64 | int *p = (int *)__builtin_alloca(sizeof(int)); |
65 | delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}} |
66 | } |
67 | |
68 | //--------------- test new family |
69 | void testNew1() { |
70 | int *p = new int; |
71 | free(p); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not free()}} |
72 | } |
73 | |
74 | void testNew2() { |
75 | int *p = (int *)operator new(0); |
76 | free(p); // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not free()}} |
77 | } |
78 | |
79 | void testNew3() { |
80 | int *p = new int[1]; |
81 | free(p); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not free()}} |
82 | } |
83 | |
84 | void testNew4() { |
85 | int *p = new int; |
86 | realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not realloc()}} |
87 | } |
88 | |
89 | void testNew5() { |
90 | int *p = (int *)operator new(0); |
91 | realloc(p, sizeof(long)); // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not realloc()}} |
92 | } |
93 | |
94 | void testNew6() { |
95 | int *p = new int[1]; |
96 | realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not realloc()}} |
97 | } |
98 | |
99 | int *allocInt() { |
100 | return new int; |
101 | } |
102 | void testNew7() { |
103 | int *p = allocInt(); |
104 | delete[] p; // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'delete[]'}} |
105 | } |
106 | |
107 | void testNew8() { |
108 | int *p = (int *)operator new(0); |
109 | delete[] p; // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not 'delete[]'}} |
110 | } |
111 | |
112 | int *allocIntArray(unsigned c) { |
113 | return new int[c]; |
114 | } |
115 | |
116 | void testNew9() { |
117 | int *p = allocIntArray(1); |
118 | delete p; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}} |
119 | } |
120 | |
121 | void testNew10() { |
122 | int *p = (int *)operator new[](0); |
123 | delete p; // expected-warning{{Memory allocated by operator new[] should be deallocated by 'delete[]', not 'delete'}} |
124 | } |
125 | |
126 | void testNew11(NSUInteger dataLength) { |
127 | int *p = new int; |
128 | NSData *d = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{+dataWithBytesNoCopy:length:freeWhenDone: cannot take ownership of memory allocated by 'new'}} |
129 | } |
130 | |
131 | //------------------------------------------------------- |
132 | // Check for intersection with unix.Malloc bounded with |
133 | // unix.MismatchedDeallocator |
134 | //------------------------------------------------------- |
135 | |
136 | // new/delete oparators are subjects of cplusplus.NewDelete. |
137 | void testNewDeleteNoWarn() { |
138 | int i; |
139 | delete &i; // no-warning |
140 | |
141 | int *p1 = new int; |
142 | delete ++p1; // no-warning |
143 | |
144 | int *p2 = new int; |
145 | delete p2; |
146 | delete p2; // no-warning |
147 | |
148 | int *p3 = new int; // no-warning |
149 | } |
150 | |
151 | void testDeleteOpAfterFree() { |
152 | int *p = (int *)malloc(sizeof(int)); |
153 | free(p); |
154 | operator delete(p); // no-warning |
155 | } |
156 | |
157 | void testDeleteAfterFree() { |
158 | int *p = (int *)malloc(sizeof(int)); |
159 | free(p); |
160 | delete p; // no-warning |
161 | } |
162 | |
163 | void testStandardPlacementNewAfterFree() { |
164 | int *p = (int *)malloc(sizeof(int)); |
165 | free(p); |
166 | p = new(p) int; // no-warning |
167 | } |
168 | |
169 | //--------------------------------------------------------------- |
170 | // Check for intersection with cplusplus.NewDelete bounded with |
171 | // unix.MismatchedDeallocator |
172 | //--------------------------------------------------------------- |
173 | |
174 | // malloc()/free() are subjects of unix.Malloc and unix.MallocWithAnnotations |
175 | void testMallocFreeNoWarn() { |
176 | int i; |
177 | free(&i); // no-warning |
178 | |
179 | int *p1 = (int *)malloc(sizeof(int)); |
180 | free(++p1); // no-warning |
181 | |
182 | int *p2 = (int *)malloc(sizeof(int)); |
183 | free(p2); |
184 | free(p2); // no-warning |
185 | |
186 | int *p3 = (int *)malloc(sizeof(int)); // no-warning |
187 | } |
188 | |
189 | void testFreeAfterDelete() { |
190 | int *p = new int; |
191 | delete p; |
192 | free(p); // no-warning |
193 | } |
194 | |
195 | void testStandardPlacementNewAfterDelete() { |
196 | int *p = new int; |
197 | delete p; |
198 | p = new(p) int; // no-warning |
199 | } |
200 | |
201 | |
202 | // Smart pointer example |
203 | template <typename T> |
204 | struct SimpleSmartPointer { |
205 | T *ptr; |
206 | |
207 | explicit SimpleSmartPointer(T *p = 0) : ptr(p) {} |
208 | ~SimpleSmartPointer() { |
209 | delete ptr; |
210 | // expected-warning@-1 {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}} |
211 | // expected-warning@-2 {{Memory allocated by malloc() should be deallocated by free(), not 'delete'}} |
212 | } |
213 | }; |
214 | |
215 | void testSimpleSmartPointerArrayNew() { |
216 | { |
217 | SimpleSmartPointer<int> a(new int); |
218 | } // no-warning |
219 | |
220 | { |
221 | SimpleSmartPointer<int> a(new int[4]); |
222 | } |
223 | } |
224 | |
225 | void testSimpleSmartPointerMalloc() { |
226 | { |
227 | SimpleSmartPointer<int> a(new int); |
228 | } // no-warning |
229 | |
230 | { |
231 | SimpleSmartPointer<int> a((int *)malloc(4)); |
232 | } |
233 | } |
234 | |