|  | // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s | 
|  | #import "Inputs/system-header-simulator-objc.h" | 
|  | #import "Inputs/system-header-simulator-for-malloc.h" | 
|  |  | 
|  | // Done with headers. Start testing. | 
|  | void testNSDatafFreeWhenDoneNoError(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength]; | 
|  | } | 
|  |  | 
|  | void testNSDataFreeWhenDoneYES(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  | void testNSDataFreeWhenDoneYES2(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  | void testNSDataFreeWhenDoneYES2_with_wrapper(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | Wrapper *nsdata = [[Wrapper alloc] initWithBytesNoCopy:data length:dataLength]; // no-warning | 
|  | } | 
|  |  | 
|  | void testNSStringFreeWhenDoneYES3(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; | 
|  | } | 
|  |  | 
|  | void testNSStringFreeWhenDoneYES4(NSUInteger dataLength) { | 
|  | unichar *data = (unichar*)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; | 
|  | free(data); //expected-warning {{Attempt to free non-owned memory}} | 
|  | } | 
|  |  | 
|  | void testNSStringFreeWhenDoneYES(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  | void testNSStringFreeWhenDoneYES2(NSUInteger dataLength) { | 
|  | unichar *data = (unichar*)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  |  | 
|  | void testNSDataFreeWhenDoneNO(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  | void testNSDataFreeWhenDoneNO2(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  |  | 
|  | void testNSStringFreeWhenDoneNO(NSUInteger dataLength) { | 
|  | unsigned char *data = (unsigned char *)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  | void testNSStringFreeWhenDoneNO2(NSUInteger dataLength) { | 
|  | unichar *data = (unichar*)malloc(42); | 
|  | NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  | void testOffsetFree() { | 
|  | int *p = (int *)malloc(sizeof(int)); | 
|  | 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()}} | 
|  | } | 
|  |  | 
|  | void testRelinquished1() { | 
|  | void *data = malloc(42); | 
|  | NSData *nsdata = [NSData dataWithBytesNoCopy:data length:42 freeWhenDone:1]; | 
|  | free(data); // expected-warning {{Attempt to free non-owned memory}} | 
|  | } | 
|  |  | 
|  | void testRelinquished2() { | 
|  | void *data = malloc(42); | 
|  | NSData *nsdata; | 
|  | free(data); | 
|  | [NSData dataWithBytesNoCopy:data length:42]; // expected-warning {{Attempt to free released memory}} | 
|  | } | 
|  |  | 
|  | void testNoCopy() { | 
|  | char *p = (char *)calloc(sizeof(int), 1); | 
|  | CustomData *w = [CustomData somethingNoCopy:p]; // no-warning | 
|  | } | 
|  |  | 
|  | void testFreeWhenDone() { | 
|  | char *p = (char *)calloc(sizeof(int), 1); | 
|  | CustomData *w = [CustomData something:p freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  | void testFreeWhenDonePositive() { | 
|  | char *p = (char *)calloc(sizeof(int), 1); | 
|  | CustomData *w = [CustomData something:p freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  | void testFreeWhenDoneNoCopy() { | 
|  | int *p = (int *)malloc(sizeof(int)); | 
|  | CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:1]; // no-warning | 
|  | } | 
|  |  | 
|  | void testFreeWhenDoneNoCopyPositive() { | 
|  | int *p = (int *)malloc(sizeof(int)); | 
|  | CustomData *w = [CustomData somethingNoCopy:p length:sizeof(int) freeWhenDone:0]; // expected-warning{{leak}} | 
|  | } | 
|  |  | 
|  | // Test CF/NS...NoCopy. PR12100: Pointers can escape when custom deallocators are provided. | 
|  | void testNSDatafFreeWhenDone(NSUInteger dataLength) { | 
|  | CFStringRef str; | 
|  | char *bytes = (char*)malloc(12); | 
|  | str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no warning | 
|  | CFRelease(str); // default allocator also frees bytes | 
|  | } | 
|  |  | 
|  | void stringWithExternalContentsExample(void) { | 
|  | #define BufferSize 1000 | 
|  | CFMutableStringRef mutStr; | 
|  | UniChar *myBuffer; | 
|  |  | 
|  | myBuffer = (UniChar *)malloc(BufferSize * sizeof(UniChar)); | 
|  |  | 
|  | mutStr = CFStringCreateMutableWithExternalCharactersNoCopy(0, myBuffer, 0, BufferSize, kCFAllocatorNull); // expected-warning{{leak}} | 
|  |  | 
|  | CFRelease(mutStr); | 
|  | //free(myBuffer); | 
|  | } | 
|  |  | 
|  | // PR12101 : pointers can escape through custom deallocators set on creation of a container. | 
|  | void TestCallbackReleasesMemory(CFDictionaryKeyCallBacks keyCallbacks) { | 
|  | void *key = malloc(12); | 
|  | void *val = malloc(12); | 
|  | CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks); | 
|  | CFDictionarySetValue(x, key, val); | 
|  | return;// no-warning | 
|  | } | 
|  |  | 
|  | NSData *radar10976702() { | 
|  | void *bytes = malloc(10); | 
|  | return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning | 
|  | } | 
|  |  | 
|  | void testBlocks() { | 
|  | int *x= (int*)malloc(sizeof(int)); | 
|  | int (^myBlock)(int) = ^(int num) { | 
|  | free(x); | 
|  | return num; | 
|  | }; | 
|  | myBlock(3); | 
|  | } | 
|  |  | 
|  | // Test NSMapInsert. | 
|  | @interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration> | 
|  | @end | 
|  | extern void *NSMapGet(NSMapTable *table, const void *key); | 
|  | extern void NSMapInsert(NSMapTable *table, const void *key, const void *value); | 
|  | extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value); | 
|  | char *strdup(const char *s); | 
|  |  | 
|  | NSString * radar11152419(NSString *string1, NSMapTable *map) { | 
|  | const char *strkey = "key"; | 
|  | NSString *string = ( NSString *)NSMapGet(map, strkey); | 
|  | if (!string) { | 
|  | string = [string1 copy]; | 
|  | NSMapInsert(map, strdup(strkey), (void*)string); // no warning | 
|  | NSMapInsertKnownAbsent(map, strdup(strkey), (void*)string); // no warning | 
|  | } | 
|  | return string; | 
|  | } | 
|  |  | 
|  | // Test that we handle pointer escaping through OSAtomicEnqueue. | 
|  | typedef volatile struct { | 
|  | void *opaque1; | 
|  | long opaque2; | 
|  | } OSQueueHead; | 
|  | void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import)); | 
|  | static inline void radar11111210(OSQueueHead *pool) { | 
|  | void *newItem = malloc(4); | 
|  | OSAtomicEnqueue(pool, newItem, 4); | 
|  | } | 
|  |  | 
|  | // Pointer might escape through CGDataProviderCreateWithData (radar://11187558). | 
|  | typedef struct CGDataProvider *CGDataProviderRef; | 
|  | typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data, | 
|  | size_t size); | 
|  | extern CGDataProviderRef CGDataProviderCreateWithData(void *info, | 
|  | const void *data, size_t size, | 
|  | CGDataProviderReleaseDataCallback releaseData) | 
|  | __attribute__((visibility("default"))); | 
|  | void *calloc(size_t, size_t); | 
|  |  | 
|  | static void releaseDataCallback (void *info, const void *data, size_t size) { | 
|  | #pragma unused (info, size) | 
|  | free((void*)data); | 
|  | } | 
|  | void testCGDataProviderCreateWithData() { | 
|  | void* b = calloc(8, 8); | 
|  | CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback); | 
|  | } | 
|  |  | 
|  | // Assume that functions which take a function pointer can free memory even if | 
|  | // they are defined in system headers and take the const pointer to the | 
|  | // allocated memory. (radar://11160612) | 
|  | extern CGDataProviderRef UnknownFunWithCallback(void *info, | 
|  | const void *data, size_t size, | 
|  | CGDataProviderReleaseDataCallback releaseData) | 
|  | __attribute__((visibility("default"))); | 
|  | void testUnknownFunWithCallBack() { | 
|  | void* b = calloc(8, 8); | 
|  | CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback); | 
|  | } | 
|  |  | 
|  | // Test blocks. | 
|  | void acceptBlockParam(void *, void (^block)(void *), unsigned); | 
|  | void testCallWithBlockCallback() { | 
|  | void *l = malloc(12); | 
|  | acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *)); | 
|  | } | 
|  |  | 
|  | // Test blocks in system headers. | 
|  | void testCallWithBlockCallbackInSystem() { | 
|  | void *l = malloc(12); | 
|  | SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *)); | 
|  | } | 
|  |  | 
|  | // Test escape into NSPointerArray. radar://11691035, PR13140 | 
|  | void foo(NSPointerArray* pointerArray) { | 
|  |  | 
|  | void* p1 = malloc (1024); | 
|  | if (p1) { | 
|  | [pointerArray addPointer:p1]; | 
|  | } | 
|  |  | 
|  | void* p2 = malloc (1024); | 
|  | if (p2) { | 
|  | [pointerArray insertPointer:p2 atIndex:1]; | 
|  | } | 
|  |  | 
|  | void* p3 = malloc (1024); | 
|  | if (p3) { | 
|  | [pointerArray replacePointerAtIndex:1 withPointer:p3]; | 
|  | } | 
|  |  | 
|  | // Freeing the buffer is allowed. | 
|  | void* buffer = [pointerArray pointerAtIndex:0]; | 
|  | free(buffer); | 
|  | } | 
|  |  | 
|  | void noCrashOnVariableArgumentSelector() { | 
|  | NSMutableString *myString = [NSMutableString stringWithString:@"some text"]; | 
|  | [myString appendFormat:@"some text = %d", 3]; | 
|  | } | 
|  |  | 
|  | void test12365078_check() { | 
|  | unichar *characters = (unichar*)malloc(12); | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string) free(characters); // no-warning | 
|  | } | 
|  |  | 
|  | void test12365078_nocheck() { | 
|  | unichar *characters = (unichar*)malloc(12); | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | } | 
|  |  | 
|  | void test12365078_false_negative() { | 
|  | unichar *characters = (unichar*)malloc(12); | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string) {;} | 
|  | } | 
|  |  | 
|  | void test12365078_no_malloc(unichar *characters) { | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string) {free(characters);} | 
|  | } | 
|  |  | 
|  | NSString *test12365078_no_malloc_returnValue(unichar *characters) { | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string) { | 
|  | return 0; // no-warning | 
|  | } | 
|  | return string; | 
|  | } | 
|  |  | 
|  | void test12365078_nocheck_nomalloc(unichar *characters) { | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | free(characters); // expected-warning {{Attempt to free non-owned memory}} | 
|  | } | 
|  |  | 
|  | void test12365078_nested(unichar *characters) { | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string) { | 
|  | NSString *string2 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string2) { | 
|  | NSString *string3 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string3) { | 
|  | NSString *string4 = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (!string4) | 
|  | free(characters); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void test12365078_check_positive() { | 
|  | unichar *characters = (unichar*)malloc(12); | 
|  | NSString *string = [[NSString alloc] initWithCharactersNoCopy:characters length:12 freeWhenDone:1]; | 
|  | if (string) free(characters); // expected-warning{{Attempt to free non-owned memory}} | 
|  | } |