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