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