blob: c7fe86bf0bcc3c68967aaad6ea02fb9684bcadc1 [file] [log] [blame]
Anna Zaks9fe80982012-03-22 00:57:20 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s
Jordan Rose613f3c02013-03-09 00:59:10 +00002#import "Inputs/system-header-simulator-objc.h"
3#import "Inputs/system-header-simulator-for-malloc.h"
Anna Zaksa7b1c472012-12-11 00:17:53 +00004
Anna Zaks33c364b2012-02-16 22:26:15 +00005// Done with headers. Start testing.
6void testNSDatafFreeWhenDoneNoError(NSUInteger dataLength) {
7 unsigned char *data = (unsigned char *)malloc(42);
8 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength];
Anna Zaks33c364b2012-02-16 22:26:15 +00009}
10
Anna Zaks7ac344a2012-02-24 23:56:53 +000011void testNSDataFreeWhenDoneYES(NSUInteger dataLength) {
12 unsigned char *data = (unsigned char *)malloc(42);
13 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
14}
15
16void testNSDataFreeWhenDoneYES2(NSUInteger dataLength) {
17 unsigned char *data = (unsigned char *)malloc(42);
18 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
19}
20
Anna Zaksa7b1c472012-12-11 00:17:53 +000021void testNSDataFreeWhenDoneYES2_with_wrapper(NSUInteger dataLength) {
22 unsigned char *data = (unsigned char *)malloc(42);
23 Wrapper *nsdata = [[Wrapper alloc] initWithBytesNoCopy:data length:dataLength]; // no-warning
24}
25
Anna Zaks26712c82012-06-22 22:42:30 +000026void testNSStringFreeWhenDoneYES3(NSUInteger dataLength) {
27 unsigned char *data = (unsigned char *)malloc(42);
28 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1];
29}
30
31void testNSStringFreeWhenDoneYES4(NSUInteger dataLength) {
32 unichar *data = (unichar*)malloc(42);
33 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1];
34 free(data); //expected-warning {{Attempt to free non-owned memory}}
35}
Anna Zaks7ac344a2012-02-24 23:56:53 +000036
37void testNSStringFreeWhenDoneYES(NSUInteger dataLength) {
38 unsigned char *data = (unsigned char *)malloc(42);
39 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; // no-warning
40}
41
42void testNSStringFreeWhenDoneYES2(NSUInteger dataLength) {
43 unichar *data = (unichar*)malloc(42);
44 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
45}
46
47
48void testNSDataFreeWhenDoneNO(NSUInteger dataLength) {
49 unsigned char *data = (unsigned char *)malloc(42);
50 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
51}
52
53void testNSDataFreeWhenDoneNO2(NSUInteger dataLength) {
54 unsigned char *data = (unsigned char *)malloc(42);
55 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
56}
57
58
59void testNSStringFreeWhenDoneNO(NSUInteger dataLength) {
60 unsigned char *data = (unsigned char *)malloc(42);
61 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:0]; // expected-warning{{leak}}
62}
63
64void testNSStringFreeWhenDoneNO2(NSUInteger dataLength) {
65 unichar *data = (unichar*)malloc(42);
66 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
67}
68
Jordan Rose613f3c02013-03-09 00:59:10 +000069void testOffsetFree() {
70 int *p = (int *)malloc(sizeof(int));
Anton Yartsev05789592013-03-28 17:05:19 +000071 NSData *nsdata = [NSData dataWithBytesNoCopy:++p length:sizeof(int) freeWhenDone:1]; // expected-warning{{Argument to +dataWithBytesNoCopy:length:freeWhenDone: is offset by 4 bytes from the start of memory allocated by malloc()}}
Jordan Rose613f3c02013-03-09 00:59:10 +000072}
73
Anna Zaks0d6989b2012-06-22 02:04:31 +000074void testRelinquished1() {
75 void *data = malloc(42);
76 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:42 freeWhenDone:1];
77 free(data); // expected-warning {{Attempt to free non-owned memory}}
78}
79
80void testRelinquished2() {
81 void *data = malloc(42);
82 NSData *nsdata;
83 free(data);
Anton Yartsevcb2ccd62013-04-10 22:21:41 +000084 [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Use of memory after it is freed}}
85}
86
87@interface My
88+ (void)param:(void *)p;
89@end
90
91void testUseAfterFree() {
92 int *p = (int *)malloc(sizeof(int));
93 free(p);
94 [My param:p]; // expected-warning{{Use of memory after it is freed}}
Anna Zaks33c364b2012-02-16 22:26:15 +000095}
Anna Zaks06a77fc2012-02-28 01:54:22 +000096
Jordan Rose613f3c02013-03-09 00:59:10 +000097void testNoCopy() {
98 char *p = (char *)calloc(sizeof(int), 1);
99 CustomData *w = [CustomData somethingNoCopy:p]; // no-warning
100}
101
102void testFreeWhenDone() {
103 char *p = (char *)calloc(sizeof(int), 1);
104 CustomData *w = [CustomData something:p freeWhenDone:1]; // no-warning
105}
106
107void testFreeWhenDonePositive() {
108 char *p = (char *)calloc(sizeof(int), 1);
109 CustomData *w = [CustomData something:p freeWhenDone:0]; // expected-warning{{leak}}
110}
111
112void testFreeWhenDoneNoCopy() {
113 int *p = (int *)malloc(sizeof(int));
114 CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:1]; // no-warning
115}
116
117void testFreeWhenDoneNoCopyPositive() {
118 int *p = (int *)malloc(sizeof(int));
119 CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:0]; // expected-warning{{leak}}
120}
121
Anna Zakse0c03ca2012-02-29 18:42:47 +0000122// Test CF/NS...NoCopy. PR12100: Pointers can escape when custom deallocators are provided.
Anna Zaks06a77fc2012-02-28 01:54:22 +0000123void testNSDatafFreeWhenDone(NSUInteger dataLength) {
124 CFStringRef str;
125 char *bytes = (char*)malloc(12);
126 str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no warning
127 CFRelease(str); // default allocator also frees bytes
128}
129
130void stringWithExternalContentsExample(void) {
131#define BufferSize 1000
132 CFMutableStringRef mutStr;
133 UniChar *myBuffer;
134
135 myBuffer = (UniChar *)malloc(BufferSize * sizeof(UniChar));
136
137 mutStr = CFStringCreateMutableWithExternalCharactersNoCopy(0, myBuffer, 0, BufferSize, kCFAllocatorNull); // expected-warning{{leak}}
138
139 CFRelease(mutStr);
140 //free(myBuffer);
141}
Anna Zakse0c03ca2012-02-29 18:42:47 +0000142
143// PR12101 : pointers can escape through custom deallocators set on creation of a container.
144void TestCallbackReleasesMemory(CFDictionaryKeyCallBacks keyCallbacks) {
145 void *key = malloc(12);
146 void *val = malloc(12);
147 CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks);
148 CFDictionarySetValue(x, key, val);
149 return;// no-warning
150}
Anna Zaks12a8b902012-03-05 17:42:10 +0000151
152NSData *radar10976702() {
153 void *bytes = malloc(10);
154 return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning
155}
156
Anna Zaks9fe80982012-03-22 00:57:20 +0000157void testBlocks() {
158 int *x= (int*)malloc(sizeof(int));
159 int (^myBlock)(int) = ^(int num) {
160 free(x);
161 return num;
162 };
163 myBlock(3);
164}
165
Anna Zaks90ab9bf2012-03-30 05:48:16 +0000166// Test NSMapInsert.
167@interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration>
168@end
169extern void *NSMapGet(NSMapTable *table, const void *key);
170extern void NSMapInsert(NSMapTable *table, const void *key, const void *value);
171extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value);
172char *strdup(const char *s);
173
174NSString * radar11152419(NSString *string1, NSMapTable *map) {
175 const char *strkey = "key";
176 NSString *string = ( NSString *)NSMapGet(map, strkey);
177 if (!string) {
178 string = [string1 copy];
179 NSMapInsert(map, strdup(strkey), (void*)string); // no warning
180 NSMapInsertKnownAbsent(map, strdup(strkey), (void*)string); // no warning
181 }
182 return string;
183}
184
Anna Zaksa651c402012-03-26 18:18:39 +0000185// Test that we handle pointer escaping through OSAtomicEnqueue.
186typedef volatile struct {
187 void *opaque1;
188 long opaque2;
189} OSQueueHead;
190void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import));
191static inline void radar11111210(OSQueueHead *pool) {
192 void *newItem = malloc(4);
193 OSAtomicEnqueue(pool, newItem, 4);
194}
195
Anna Zakse8628c52012-04-06 01:00:47 +0000196// Pointer might escape through CGDataProviderCreateWithData (radar://11187558).
197typedef struct CGDataProvider *CGDataProviderRef;
198typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data,
199 size_t size);
200extern CGDataProviderRef CGDataProviderCreateWithData(void *info,
201 const void *data, size_t size,
202 CGDataProviderReleaseDataCallback releaseData)
203 __attribute__((visibility("default")));
204void *calloc(size_t, size_t);
205
206static void releaseDataCallback (void *info, const void *data, size_t size) {
207#pragma unused (info, size)
208 free((void*)data);
209}
210void testCGDataProviderCreateWithData() {
211 void* b = calloc(8, 8);
212 CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback);
Anna Zaks228f9c72012-05-03 23:50:28 +0000213}
214
215// Assume that functions which take a function pointer can free memory even if
216// they are defined in system headers and take the const pointer to the
217// allocated memory. (radar://11160612)
218extern CGDataProviderRef UnknownFunWithCallback(void *info,
219 const void *data, size_t size,
220 CGDataProviderReleaseDataCallback releaseData)
221 __attribute__((visibility("default")));
222void testUnknownFunWithCallBack() {
223 void* b = calloc(8, 8);
224 CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback);
225}
226
227// Test blocks.
228void acceptBlockParam(void *, void (^block)(void *), unsigned);
229void testCallWithBlockCallback() {
230 void *l = malloc(12);
231 acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
232}
233
234// Test blocks in system headers.
235void testCallWithBlockCallbackInSystem() {
236 void *l = malloc(12);
237 SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
Anna Zaks42908c72012-06-19 05:10:32 +0000238}
239
240// Test escape into NSPointerArray. radar://11691035, PR13140
241void foo(NSPointerArray* pointerArray) {
242
243 void* p1 = malloc (1024);
244 if (p1) {
245 [pointerArray addPointer:p1];
246 }
247
248 void* p2 = malloc (1024);
249 if (p2) {
250 [pointerArray insertPointer:p2 atIndex:1];
251 }
252
253 void* p3 = malloc (1024);
254 if (p3) {
255 [pointerArray replacePointerAtIndex:1 withPointer:p3];
256 }
257
258 // Freeing the buffer is allowed.
259 void* buffer = [pointerArray pointerAtIndex:0];
260 free(buffer);
Anna Zakse4b6d5e2012-06-22 22:08:09 +0000261}
262
263void noCrashOnVariableArgumentSelector() {
264 NSMutableString *myString = [NSMutableString stringWithString:@"some text"];
265 [myString appendFormat:@"some text = %d", 3];
Chandler Carruth66a34a62012-09-12 01:11:10 +0000266}
Anna Zaks67291b92012-11-13 03:18:01 +0000267
268void test12365078_check() {
269 unichar *characters = (unichar*)malloc(12);
270 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
271 if (!string) free(characters); // no-warning
272}
273
274void test12365078_nocheck() {
275 unichar *characters = (unichar*)malloc(12);
276 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
277}
278
279void test12365078_false_negative() {
280 unichar *characters = (unichar*)malloc(12);
281 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
282 if (!string) {;}
283}
284
285void test12365078_no_malloc(unichar *characters) {
286 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
287 if (!string) {free(characters);}
288}
289
Anna Zaksde138142012-11-13 03:34:49 +0000290NSString *test12365078_no_malloc_returnValue(unichar *characters) {
Anna Zaks67291b92012-11-13 03:18:01 +0000291 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
Anna Zaksde138142012-11-13 03:34:49 +0000292 if (!string) {
293 return 0; // no-warning
294 }
295 return string;
Anna Zaks67291b92012-11-13 03:18:01 +0000296}
297
298void test12365078_nocheck_nomalloc(unichar *characters) {
299 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
300 free(characters); // expected-warning {{Attempt to free non-owned memory}}
301}
302
303void test12365078_nested(unichar *characters) {
304 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
305 if (!string) {
306 NSString *string2 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
307 if (!string2) {
308 NSString *string3 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
309 if (!string3) {
310 NSString *string4 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
311 if (!string4)
312 free(characters);
313 }
314 }
315 }
316}
Anna Zaksa14c1d02012-11-13 19:47:40 +0000317
318void test12365078_check_positive() {
319 unichar *characters = (unichar*)malloc(12);
320 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
321 if (string) free(characters); // expected-warning{{Attempt to free non-owned memory}}
322}