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