malloc.mm revision aca0ac58d2ae80d764e3832456667d7322445e0c
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s 2#include "system-header-simulator-objc.h" 3 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]; 12 free(data); // no warning 13} 14 15void testNSDataFreeWhenDoneYES(NSUInteger dataLength) { 16 unsigned char *data = (unsigned char *)malloc(42); 17 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning 18} 19 20void testNSDataFreeWhenDoneYES2(NSUInteger dataLength) { 21 unsigned char *data = (unsigned char *)malloc(42); 22 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:1]; // no-warning 23} 24 25 26void testNSStringFreeWhenDoneYES(NSUInteger dataLength) { 27 unsigned char *data = (unsigned char *)malloc(42); 28 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:1]; // no-warning 29} 30 31void testNSStringFreeWhenDoneYES2(NSUInteger dataLength) { 32 unichar *data = (unichar*)malloc(42); 33 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:1]; // no-warning 34} 35 36 37void testNSDataFreeWhenDoneNO(NSUInteger dataLength) { 38 unsigned char *data = (unsigned char *)malloc(42); 39 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} 40} 41 42void testNSDataFreeWhenDoneNO2(NSUInteger dataLength) { 43 unsigned char *data = (unsigned char *)malloc(42); 44 NSData *nsdata = [[NSData alloc] initWithBytesNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} 45} 46 47 48void testNSStringFreeWhenDoneNO(NSUInteger dataLength) { 49 unsigned char *data = (unsigned char *)malloc(42); 50 NSString *nsstr = [[NSString alloc] initWithBytesNoCopy:data length:dataLength encoding:NSUTF8StringEncoding freeWhenDone:0]; // expected-warning{{leak}} 51} 52 53void testNSStringFreeWhenDoneNO2(NSUInteger dataLength) { 54 unichar *data = (unichar*)malloc(42); 55 NSString *nsstr = [[NSString alloc] initWithCharactersNoCopy:data length:dataLength freeWhenDone:0]; // expected-warning{{leak}} 56} 57 58// TODO: False Negative. 59void testNSDatafFreeWhenDoneFN(NSUInteger dataLength) { 60 unsigned char *data = (unsigned char *)malloc(42); 61 NSData *nsdata = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:1]; 62 free(data); // false negative 63} 64 65// Test CF/NS...NoCopy. PR12100: Pointers can escape when custom deallocators are provided. 66void testNSDatafFreeWhenDone(NSUInteger dataLength) { 67 CFStringRef str; 68 char *bytes = (char*)malloc(12); 69 str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no warning 70 CFRelease(str); // default allocator also frees bytes 71} 72 73void stringWithExternalContentsExample(void) { 74#define BufferSize 1000 75 CFMutableStringRef mutStr; 76 UniChar *myBuffer; 77 78 myBuffer = (UniChar *)malloc(BufferSize * sizeof(UniChar)); 79 80 mutStr = CFStringCreateMutableWithExternalCharactersNoCopy(0, myBuffer, 0, BufferSize, kCFAllocatorNull); // expected-warning{{leak}} 81 82 CFRelease(mutStr); 83 //free(myBuffer); 84} 85 86// PR12101 : pointers can escape through custom deallocators set on creation of a container. 87void TestCallbackReleasesMemory(CFDictionaryKeyCallBacks keyCallbacks) { 88 void *key = malloc(12); 89 void *val = malloc(12); 90 CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks); 91 CFDictionarySetValue(x, key, val); 92 return;// no-warning 93} 94 95NSData *radar10976702() { 96 void *bytes = malloc(10); 97 return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning 98} 99 100void testBlocks() { 101 int *x= (int*)malloc(sizeof(int)); 102 int (^myBlock)(int) = ^(int num) { 103 free(x); 104 return num; 105 }; 106 myBlock(3); 107} 108 109// Test NSMapInsert. 110@interface NSMapTable : NSObject <NSCopying, NSCoding, NSFastEnumeration> 111@end 112extern void *NSMapGet(NSMapTable *table, const void *key); 113extern void NSMapInsert(NSMapTable *table, const void *key, const void *value); 114extern void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value); 115char *strdup(const char *s); 116 117NSString * radar11152419(NSString *string1, NSMapTable *map) { 118 const char *strkey = "key"; 119 NSString *string = ( NSString *)NSMapGet(map, strkey); 120 if (!string) { 121 string = [string1 copy]; 122 NSMapInsert(map, strdup(strkey), (void*)string); // no warning 123 NSMapInsertKnownAbsent(map, strdup(strkey), (void*)string); // no warning 124 } 125 return string; 126} 127 128// Test that we handle pointer escaping through OSAtomicEnqueue. 129typedef volatile struct { 130 void *opaque1; 131 long opaque2; 132} OSQueueHead; 133void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import)); 134static inline void radar11111210(OSQueueHead *pool) { 135 void *newItem = malloc(4); 136 OSAtomicEnqueue(pool, newItem, 4); 137} 138 139// Pointer might escape through CGDataProviderCreateWithData (radar://11187558). 140typedef struct CGDataProvider *CGDataProviderRef; 141typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data, 142 size_t size); 143extern CGDataProviderRef CGDataProviderCreateWithData(void *info, 144 const void *data, size_t size, 145 CGDataProviderReleaseDataCallback releaseData) 146 __attribute__((visibility("default"))); 147void *calloc(size_t, size_t); 148 149static void releaseDataCallback (void *info, const void *data, size_t size) { 150#pragma unused (info, size) 151 free((void*)data); 152} 153void testCGDataProviderCreateWithData() { 154 void* b = calloc(8, 8); 155 CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback); 156} 157 158// Assume that functions which take a function pointer can free memory even if 159// they are defined in system headers and take the const pointer to the 160// allocated memory. (radar://11160612) 161extern CGDataProviderRef UnknownFunWithCallback(void *info, 162 const void *data, size_t size, 163 CGDataProviderReleaseDataCallback releaseData) 164 __attribute__((visibility("default"))); 165void testUnknownFunWithCallBack() { 166 void* b = calloc(8, 8); 167 CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback); 168} 169 170// Test blocks. 171void acceptBlockParam(void *, void (^block)(void *), unsigned); 172void testCallWithBlockCallback() { 173 void *l = malloc(12); 174 acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *)); 175} 176 177// Test blocks in system headers. 178void testCallWithBlockCallbackInSystem() { 179 void *l = malloc(12); 180 SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *)); 181}