[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / malloc.mm
blob1b7dd2756e1bb3920f034d0359a08b9d35359ccf
1 // RUN: %clang_analyze_cc1 -std=c++14 \
2 // RUN:     -analyzer-checker=core,unix.Malloc,cplusplus.NewDelete \
3 // RUN:     -analyzer-checker=unix.MismatchedDeallocator \
4 // RUN:     -verify -fblocks %s
6 #import "Inputs/system-header-simulator-objc.h"
7 #import "Inputs/system-header-simulator-for-malloc.h"
9 // Done with headers. Start testing.
10 void testNSDatafFreeWhenDoneNoError(NSUInteger dataLength) {
11   unsigned char *data = (unsigned char *)malloc(42);
12   NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength];
15 void testNSDataFreeWhenDoneYES(NSUInteger dataLength) {
16   unsigned char *data = (unsigned char *)malloc(42);
17   NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
20 void testNSDataFreeWhenDoneYES2(NSUInteger dataLength) {
21   unsigned char *data = (unsigned char *)malloc(42);
22   NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
25 void testNSDataFreeWhenDoneYES2_with_wrapper(NSUInteger dataLength) {
26   unsigned char *data = (unsigned char *)malloc(42);
27   Wrapper *nsdata = [[Wrapper alloc] initWithBytesNoCopy:data length:dataLength]; // no-warning
30 void testNSStringFreeWhenDoneYES3(NSUInteger dataLength) {
31   unsigned char *data = (unsigned char *)malloc(42);
32   NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1];
35 void testNSStringFreeWhenDoneYES4(NSUInteger dataLength) {
36   unichar *data = (unichar*)malloc(42);
37   NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1];
38   free(data); //expected-warning {{Attempt to free non-owned memory}}
41 void testNSStringFreeWhenDoneYES(NSUInteger dataLength) {
42   unsigned char *data = (unsigned char *)malloc(42);
43   NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; // no-warning
46 void testNSStringFreeWhenDoneYES2(NSUInteger dataLength) {
47   unichar *data = (unichar*)malloc(42);
48   NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; // no-warning
52 void testNSDataFreeWhenDoneNO(NSUInteger dataLength) {
53   unsigned char *data = (unsigned char *)malloc(42);
54   NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
57 void testNSDataFreeWhenDoneNO2(NSUInteger dataLength) {
58   unsigned char *data = (unsigned char *)malloc(42);
59   NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
63 void testNSStringFreeWhenDoneNO(NSUInteger dataLength) {
64   unsigned char *data = (unsigned char *)malloc(42);
65   NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:0]; // expected-warning{{leak}}
68 void testNSStringFreeWhenDoneNewDelete(NSUInteger dataLength) {
69   unsigned char *data = new unsigned char(42);
70   NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data
71                                    length:dataLength freeWhenDone:1];
72   // expected-warning@-2{{-initWithBytesNoCopy:length:freeWhenDone: cannot take ownership of memory allocated by 'new'}}
75 void testNSStringFreeWhenDoneNewDelete2(NSUInteger dataLength) {
76   unsigned char *data = new unsigned char(42);
77   NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data
78                                                 length:dataLength
79                                            deallocator:^(void *bytes,
80                                                          NSUInteger length) {
81                                              delete (unsigned char *)bytes;
82                                            }]; // no-warning
85 void testNSStringFreeWhenDoneNO2(NSUInteger dataLength) {
86   unichar *data = (unichar*)malloc(42);
87   NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}}
90 void testOffsetFree() {
91   int *p = (int *)malloc(sizeof(int));
92   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()}}
95 void testRelinquished1() {
96   void *data = malloc(42);
97   NSData *nsdata = [NSData dataWithBytesNoCopy:data length:42 freeWhenDone:1];
98   free(data); // expected-warning {{Attempt to free non-owned memory}}
101 void testRelinquished2() {
102   void *data = malloc(42);
103   NSData *nsdata;
104   free(data);
105   [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Use of memory after it is freed}}
108 @interface My
109 + (void)param:(void *)p;
110 @end
112 void testUseAfterFree() {
113   int *p = (int *)malloc(sizeof(int));
114   free(p);
115   [My param:p];  // expected-warning{{Use of memory after it is freed}}
118 void testNoCopy() {
119   char *p = (char *)calloc(sizeof(int), 1);
120   CustomData *w = [CustomData somethingNoCopy:p]; // no-warning
123 void testFreeWhenDone() {
124   char *p = (char *)calloc(sizeof(int), 1);
125   CustomData *w = [CustomData something:p freeWhenDone:1]; // no-warning
128 void testFreeWhenDonePositive() {
129   char *p = (char *)calloc(sizeof(int), 1);
130   CustomData *w = [CustomData something:p freeWhenDone:0]; // expected-warning{{leak}}
133 void testFreeWhenDoneNoCopy() {
134   int *p = (int *)malloc(sizeof(int));
135   CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:1]; // no-warning
138 void testFreeWhenDoneNoCopyPositive() {
139   int *p = (int *)malloc(sizeof(int));
140   CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:0]; // expected-warning{{leak}}
143 // Test CF/NS...NoCopy. PR12100: Pointers can escape when custom deallocators are provided.
144 void testNSDatafFreeWhenDone(NSUInteger dataLength) {
145   CFStringRef str;
146   char *bytes = (char*)malloc(12);
147   str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no warning
148   CFRelease(str); // default allocator also frees bytes
151 void stringWithExternalContentsExample(void) {
152 #define BufferSize 1000
153     CFMutableStringRef mutStr;
154     UniChar *myBuffer;
156     myBuffer = (UniChar *)malloc(BufferSize * sizeof(UniChar));
158     mutStr = CFStringCreateMutableWithExternalCharactersNoCopy(0, myBuffer, 0, BufferSize, kCFAllocatorNull); // expected-warning{{leak}}
160     CFRelease(mutStr);
161     //free(myBuffer);
164 // PR12101 : pointers can escape through custom deallocators set on creation of a container.
165 void TestCallbackReleasesMemory(CFDictionaryKeyCallBacks keyCallbacks) {
166   void *key = malloc(12);
167   void *val = malloc(12);
168   CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks);
169   CFDictionarySetValue(x, key, val); 
170   return;// no-warning
173 NSData *radar10976702() {
174   void *bytes = malloc(10);
175   return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning
178 void testBlocks() {
179   int *x= (int*)malloc(sizeof(int));
180   int (^myBlock)(int) = ^(int num) {
181     free(x);
182     return num;
183   };
184   myBlock(3);
187 // Test NSMapInsert. 
188 @interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration>
189 @end
190 extern void *NSMapGet(NSMapTable *table, const void *key);
191 extern void NSMapInsert(NSMapTable *table, const void *key, const void *value);
192 extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value);
193 char *strdup(const char *s);
195 NSString * radar11152419(NSString *string1, NSMapTable *map) {
196     const char *strkey = "key";
197     NSString *string = ( NSString *)NSMapGet(map, strkey);
198     if (!string) {
199         string = [string1 copy];
200         NSMapInsert(map, strdup(strkey), (void*)string); // no warning
201         NSMapInsertKnownAbsent(map, strdup(strkey), (void*)string); // no warning
202     }
203     return string;
206 // Test that we handle pointer escaping through OSAtomicEnqueue.
207 typedef volatile struct {
208  void *opaque1;
209  long opaque2;
210 } OSQueueHead;
211 extern "C" void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import));
212 static inline void radar11111210(OSQueueHead *pool) {
213     void *newItem = malloc(4);
214     OSAtomicEnqueue(pool, newItem, 4);
217 // Pointer might escape through CGDataProviderCreateWithData (radar://11187558).
218 typedef struct CGDataProvider *CGDataProviderRef;
219 typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data,
220     size_t size);
221 extern CGDataProviderRef CGDataProviderCreateWithData(void *info,
222     const void *data, size_t size,
223     CGDataProviderReleaseDataCallback releaseData)
224     __attribute__((visibility("default")));
225 void *calloc(size_t, size_t);
227 static void releaseDataCallback (void *info, const void *data, size_t size) {
228 #pragma unused (info, size)
229   free((void*)data);
231 void testCGDataProviderCreateWithData() { 
232   void* b = calloc(8, 8);
233   CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback);
236 // Assume that functions which take a function pointer can free memory even if
237 // they are defined in system headers and take the const pointer to the
238 // allocated memory. (radar://11160612)
239 extern CGDataProviderRef UnknownFunWithCallback(void *info,
240     const void *data, size_t size,
241     CGDataProviderReleaseDataCallback releaseData)
242     __attribute__((visibility("default")));
243 void testUnknownFunWithCallBack() { 
244   void* b = calloc(8, 8);
245   CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback);
248 // Test blocks.
249 void acceptBlockParam(void *, void (^block)(void *), unsigned);
250 void testCallWithBlockCallback() {
251   void *l = malloc(12);
252   acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
255 // Test blocks in system headers.
256 void testCallWithBlockCallbackInSystem() {
257   void *l = malloc(12);
258   SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
261 // Test escape into NSPointerArray. radar://11691035, PR13140
262 void foo(NSPointerArray* pointerArray) {
263   
264   void* p1 = malloc (1024);
265   if (p1) {
266     [pointerArray addPointer:p1];
267   }
269   void* p2 = malloc (1024);
270   if (p2) {
271     [pointerArray insertPointer:p2 atIndex:1];
272   }
274   void* p3 = malloc (1024);
275   if (p3) {
276     [pointerArray replacePointerAtIndex:1 withPointer:p3];
277   }
279   // Freeing the buffer is allowed.
280   void* buffer = [pointerArray pointerAtIndex:0];
281   free(buffer);
284 void noCrashOnVariableArgumentSelector() {
285   NSMutableString *myString = [NSMutableString stringWithString:@"some text"];
286   [myString appendFormat:@"some text = %d", 3];
289 void test12365078_check() {
290   unichar *characters = (unichar*)malloc(12);
291   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
292   if (!string) free(characters); // no-warning
295 void test12365078_nocheck() {
296   unichar *characters = (unichar*)malloc(12);
297   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
300 void test12365078_false_negative() {
301   unichar *characters = (unichar*)malloc(12);
302   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
303   if (!string) {;}
306 void test12365078_no_malloc(unichar *characters) {
307   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
308   if (!string) {free(characters);}
311 NSString *test12365078_no_malloc_returnValue(unichar *characters) {
312   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
313   if (!string) {
314     return 0; // no-warning
315   }
316   return string;
319 void test12365078_nocheck_nomalloc(unichar *characters) {
320   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
321   free(characters); // expected-warning {{Attempt to free non-owned memory}}
324 void test12365078_nested(unichar *characters) {
325   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
326   if (!string) {    
327     NSString *string2 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
328     if (!string2) {    
329       NSString *string3 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
330       if (!string3) {    
331         NSString *string4 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
332         if (!string4)
333           free(characters);
334       }
335     }
336   }
339 void test12365078_check_positive() {
340   unichar *characters = (unichar*)malloc(12);
341   NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1];
342   if (string) free(characters); // expected-warning{{Attempt to free non-owned memory}}
345 void *test_reinterpret_cast_to_block() {
346   // Used to leak because the pointer was disappearing
347   // during the reinterpret_cast.
348   using BlockPtrTy = void (^)();
349   struct Block {};
350   Block* block = static_cast<Block*>(malloc(sizeof(Block)));
351   BlockPtrTy blockPtr = reinterpret_cast<BlockPtrTy>(block); // no-warning
352   return blockPtr;