blob: f2a195ce1d4b96a02c8ff3f251491bc709ff401f [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
Chandler Carruth66a34a62012-09-12 01:11:10 +00002#include "Inputs/system-header-simulator-objc.h"
Anna Zaks33c364b2012-02-16 22:26:15 +00003
4typedef __typeof(sizeof(int)) size_t;
5void *malloc(size_t);
6void free(void *);
7
Anna Zaksa7b1c472012-12-11 00:17:53 +00008@interface Wrapper : NSData
9- (id)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)len;
10@end
11
12@implementation Wrapper
13- (id)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)len {
14 return [self initWithBytesNoCopy:bytes length:len freeWhenDone:1]; // no-warning
15}
16@end
17
Anna Zaks33c364b2012-02-16 22:26:15 +000018// Done with headers. Start testing.
19void testNSDatafFreeWhenDoneNoError(NSUInteger dataLength) {
20 unsigned char *data = (unsigned char *)malloc(42);
21 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength];
Anna Zaks33c364b2012-02-16 22:26:15 +000022}
23
Anna Zaks7ac344a2012-02-24 23:56:53 +000024void testNSDataFreeWhenDoneYES(NSUInteger dataLength) {
25 unsigned char *data = (unsigned char *)malloc(42);
26 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
27}
28
29void testNSDataFreeWhenDoneYES2(NSUInteger dataLength) {
30 unsigned char *data = (unsigned char *)malloc(42);
31 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
32}
33
Anna Zaksa7b1c472012-12-11 00:17:53 +000034void testNSDataFreeWhenDoneYES2_with_wrapper(NSUInteger dataLength) {
35 unsigned char *data = (unsigned char *)malloc(42);
36 Wrapper *nsdata = [[Wrapper alloc] initWithBytesNoCopy:data length:dataLength]; // no-warning
37}
38
Anna Zaks26712c82012-06-22 22:42:30 +000039void testNSStringFreeWhenDoneYES3(NSUInteger dataLength) {
40 unsigned char *data = (unsigned char *)malloc(42);
41 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1];
42}
43
44void testNSStringFreeWhenDoneYES4(NSUInteger dataLength) {
45 unichar *data = (unichar*)malloc(42);
46 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1];
47 free(data); //expected-warning {{Attempt to free non-owned memory}}
48}
Anna Zaks7ac344a2012-02-24 23:56:53 +000049
50void testNSStringFreeWhenDoneYES(NSUInteger dataLength) {
51 unsigned char *data = (unsigned char *)malloc(42);
52 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; // no-warning
53}
54
55void testNSStringFreeWhenDoneYES2(NSUInteger dataLength) {
56 unichar *data = (unichar*)malloc(42);
57 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
58}
59
60
61void testNSDataFreeWhenDoneNO(NSUInteger dataLength) {
62 unsigned char *data = (unsigned char *)malloc(42);
63 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
64}
65
66void testNSDataFreeWhenDoneNO2(NSUInteger dataLength) {
67 unsigned char *data = (unsigned char *)malloc(42);
68 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
69}
70
71
72void testNSStringFreeWhenDoneNO(NSUInteger dataLength) {
73 unsigned char *data = (unsigned char *)malloc(42);
74 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:0]; // expected-warning{{leak}}
75}
76
77void testNSStringFreeWhenDoneNO2(NSUInteger dataLength) {
78 unichar *data = (unichar*)malloc(42);
79 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
80}
81
Anna Zaks0d6989b2012-06-22 02:04:31 +000082void testRelinquished1() {
83 void *data = malloc(42);
84 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:42 freeWhenDone:1];
85 free(data); // expected-warning {{Attempt to free non-owned memory}}
86}
87
88void testRelinquished2() {
89 void *data = malloc(42);
90 NSData *nsdata;
91 free(data);
92 [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Attempt to free released memory}}
Anna Zaks33c364b2012-02-16 22:26:15 +000093}
Anna Zaks06a77fc2012-02-28 01:54:22 +000094
Anna Zakse0c03ca2012-02-29 18:42:47 +000095// Test CF/NS...NoCopy. PR12100: Pointers can escape when custom deallocators are provided.
Anna Zaks06a77fc2012-02-28 01:54:22 +000096void testNSDatafFreeWhenDone(NSUInteger dataLength) {
97 CFStringRef str;
98 char *bytes = (char*)malloc(12);
99 str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no warning
100 CFRelease(str); // default allocator also frees bytes
101}
102
103void stringWithExternalContentsExample(void) {
104#define BufferSize 1000
105 CFMutableStringRef mutStr;
106 UniChar *myBuffer;
107
108 myBuffer = (UniChar *)malloc(BufferSize * sizeof(UniChar));
109
110 mutStr = CFStringCreateMutableWithExternalCharactersNoCopy(0, myBuffer, 0, BufferSize, kCFAllocatorNull); // expected-warning{{leak}}
111
112 CFRelease(mutStr);
113 //free(myBuffer);
114}
Anna Zakse0c03ca2012-02-29 18:42:47 +0000115
116// PR12101 : pointers can escape through custom deallocators set on creation of a container.
117void TestCallbackReleasesMemory(CFDictionaryKeyCallBacks keyCallbacks) {
118 void *key = malloc(12);
119 void *val = malloc(12);
120 CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks);
121 CFDictionarySetValue(x, key, val);
122 return;// no-warning
123}
Anna Zaks12a8b902012-03-05 17:42:10 +0000124
125NSData *radar10976702() {
126 void *bytes = malloc(10);
127 return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning
128}
129
Anna Zaks9fe80982012-03-22 00:57:20 +0000130void testBlocks() {
131 int *x= (int*)malloc(sizeof(int));
132 int (^myBlock)(int) = ^(int num) {
133 free(x);
134 return num;
135 };
136 myBlock(3);
137}
138
Anna Zaks90ab9bf2012-03-30 05:48:16 +0000139// Test NSMapInsert.
140@interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration>
141@end
142extern void *NSMapGet(NSMapTable *table, const void *key);
143extern void NSMapInsert(NSMapTable *table, const void *key, const void *value);
144extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value);
145char *strdup(const char *s);
146
147NSString * radar11152419(NSString *string1, NSMapTable *map) {
148 const char *strkey = "key";
149 NSString *string = ( NSString *)NSMapGet(map, strkey);
150 if (!string) {
151 string = [string1 copy];
152 NSMapInsert(map, strdup(strkey), (void*)string); // no warning
153 NSMapInsertKnownAbsent(map, strdup(strkey), (void*)string); // no warning
154 }
155 return string;
156}
157
Anna Zaksa651c402012-03-26 18:18:39 +0000158// Test that we handle pointer escaping through OSAtomicEnqueue.
159typedef volatile struct {
160 void *opaque1;
161 long opaque2;
162} OSQueueHead;
163void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import));
164static inline void radar11111210(OSQueueHead *pool) {
165 void *newItem = malloc(4);
166 OSAtomicEnqueue(pool, newItem, 4);
167}
168
Anna Zakse8628c52012-04-06 01:00:47 +0000169// Pointer might escape through CGDataProviderCreateWithData (radar://11187558).
170typedef struct CGDataProvider *CGDataProviderRef;
171typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data,
172 size_t size);
173extern CGDataProviderRef CGDataProviderCreateWithData(void *info,
174 const void *data, size_t size,
175 CGDataProviderReleaseDataCallback releaseData)
176 __attribute__((visibility("default")));
177void *calloc(size_t, size_t);
178
179static void releaseDataCallback (void *info, const void *data, size_t size) {
180#pragma unused (info, size)
181 free((void*)data);
182}
183void testCGDataProviderCreateWithData() {
184 void* b = calloc(8, 8);
185 CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback);
Anna Zaks228f9c72012-05-03 23:50:28 +0000186}
187
188// Assume that functions which take a function pointer can free memory even if
189// they are defined in system headers and take the const pointer to the
190// allocated memory. (radar://11160612)
191extern CGDataProviderRef UnknownFunWithCallback(void *info,
192 const void *data, size_t size,
193 CGDataProviderReleaseDataCallback releaseData)
194 __attribute__((visibility("default")));
195void testUnknownFunWithCallBack() {
196 void* b = calloc(8, 8);
197 CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback);
198}
199
200// Test blocks.
201void acceptBlockParam(void *, void (^block)(void *), unsigned);
202void testCallWithBlockCallback() {
203 void *l = malloc(12);
204 acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
205}
206
207// Test blocks in system headers.
208void testCallWithBlockCallbackInSystem() {
209 void *l = malloc(12);
210 SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
Anna Zaks42908c72012-06-19 05:10:32 +0000211}
212
213// Test escape into NSPointerArray. radar://11691035, PR13140
214void foo(NSPointerArray* pointerArray) {
215
216 void* p1 = malloc (1024);
217 if (p1) {
218 [pointerArray addPointer:p1];
219 }
220
221 void* p2 = malloc (1024);
222 if (p2) {
223 [pointerArray insertPointer:p2 atIndex:1];
224 }
225
226 void* p3 = malloc (1024);
227 if (p3) {
228 [pointerArray replacePointerAtIndex:1 withPointer:p3];
229 }
230
231 // Freeing the buffer is allowed.
232 void* buffer = [pointerArray pointerAtIndex:0];
233 free(buffer);
Anna Zakse4b6d5e2012-06-22 22:08:09 +0000234}
235
236void noCrashOnVariableArgumentSelector() {
237 NSMutableString *myString = [NSMutableString stringWithString:@"some text"];
238 [myString appendFormat:@"some text = %d", 3];
Chandler Carruth66a34a62012-09-12 01:11:10 +0000239}
Anna Zaks67291b92012-11-13 03:18:01 +0000240
241void test12365078_check() {
242 unichar *characters = (unichar*)malloc(12);
243 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
244 if (!string) free(characters); // no-warning
245}
246
247void test12365078_nocheck() {
248 unichar *characters = (unichar*)malloc(12);
249 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
250}
251
252void test12365078_false_negative() {
253 unichar *characters = (unichar*)malloc(12);
254 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
255 if (!string) {;}
256}
257
258void test12365078_no_malloc(unichar *characters) {
259 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
260 if (!string) {free(characters);}
261}
262
Anna Zaksde138142012-11-13 03:34:49 +0000263NSString *test12365078_no_malloc_returnValue(unichar *characters) {
Anna Zaks67291b92012-11-13 03:18:01 +0000264 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
Anna Zaksde138142012-11-13 03:34:49 +0000265 if (!string) {
266 return 0; // no-warning
267 }
268 return string;
Anna Zaks67291b92012-11-13 03:18:01 +0000269}
270
271void test12365078_nocheck_nomalloc(unichar *characters) {
272 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
273 free(characters); // expected-warning {{Attempt to free non-owned memory}}
274}
275
276void test12365078_nested(unichar *characters) {
277 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
278 if (!string) {
279 NSString *string2 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
280 if (!string2) {
281 NSString *string3 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
282 if (!string3) {
283 NSString *string4 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
284 if (!string4)
285 free(characters);
286 }
287 }
288 }
289}
Anna Zaksa14c1d02012-11-13 19:47:40 +0000290
291void test12365078_check_positive() {
292 unichar *characters = (unichar*)malloc(12);
293 NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
294 if (string) free(characters); // expected-warning{{Attempt to free non-owned memory}}
295}