blob: 44d0a5d962df67ff2458b95e3f70e26c402169a9 [file] [log] [blame]
Ted Kremeneka3f45402009-04-29 16:03:59 +00001// RUN: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
2// RUN: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s
Ted Kremenek1670e402009-04-11 00:11:10 +00003
4
Ted Kremeneka3f45402009-04-29 16:03:59 +00005// NOTWORK: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
6// NOTWORK: clang-cc -arch i386 -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
Ted Kremenek859be3b2008-06-16 20:37:30 +00007
8//===----------------------------------------------------------------------===//
9// The following code is reduced using delta-debugging from
10// Foundation.h (Mac OS X).
11//
12// It includes the basic definitions for the test cases below.
13// Not directly including Foundation.h directly makes this test case
14// both svelte and portable to non-Mac platforms.
15//===----------------------------------------------------------------------===//
16
Ted Kremeneka3f45402009-04-29 16:03:59 +000017typedef int int32_t;
Ted Kremenek859be3b2008-06-16 20:37:30 +000018typedef const void * CFTypeRef;
19typedef const struct __CFString * CFStringRef;
20typedef const struct __CFAllocator * CFAllocatorRef;
21extern const CFAllocatorRef kCFAllocatorDefault;
22extern CFTypeRef CFRetain(CFTypeRef cf);
Ted Kremenek09f14192009-04-21 20:01:03 +000023void CFRelease(CFTypeRef cf);
Ted Kremenek859be3b2008-06-16 20:37:30 +000024typedef const struct __CFDictionary * CFDictionaryRef;
Ted Kremenek2fb78a72008-12-17 21:50:35 +000025const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key);
Ted Kremenek859be3b2008-06-16 20:37:30 +000026extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);
27typedef signed char BOOL;
28typedef int NSInteger;
29typedef unsigned int NSUInteger;
30@class NSString, Protocol;
31extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
32typedef NSInteger NSComparisonResult;
33typedef struct _NSZone NSZone;
34@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
35@protocol NSObject
36- (BOOL)isEqual:(id)object;
37- (oneway void)release;
Ted Kremenek2fb78a72008-12-17 21:50:35 +000038- (id)retain;
Ted Kremenek95d3b902009-05-11 15:26:06 +000039- (id)autorelease;
Ted Kremenek859be3b2008-06-16 20:37:30 +000040@end
41@protocol NSCopying
42- (id)copyWithZone:(NSZone *)zone;
43@end
44@protocol NSMutableCopying
45- (id)mutableCopyWithZone:(NSZone *)zone;
46@end
47@protocol NSCoding
48- (void)encodeWithCoder:(NSCoder *)aCoder;
49@end
50@interface NSObject <NSObject> {}
51- (id)init;
52+ (id)alloc;
53@end
54extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
55typedef struct {} NSFastEnumerationState;
56@protocol NSFastEnumeration
57- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
58@end
59@class NSString;
60typedef struct _NSRange {} NSRange;
61@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
62- (NSUInteger)count;
63@end
64@interface NSMutableArray : NSArray
65- (void)addObject:(id)anObject;
66- (id)initWithCapacity:(NSUInteger)numItems;
67@end
68typedef unsigned short unichar;
69@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale;
70typedef NSUInteger NSStringCompareOptions;
71@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
72- (NSComparisonResult)compare:(NSString *)string;
73- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;
74- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange;
75- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale;
76- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string;
77- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator;
Ted Kremeneke87450e2009-04-23 19:11:35 +000078+ (id)stringWithFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2)));
Ted Kremenek859be3b2008-06-16 20:37:30 +000079@end
80@interface NSSimpleCString : NSString {} @end
81@interface NSConstantString : NSSimpleCString @end
82extern void *_NSConstantStringClassReference;
83
84//===----------------------------------------------------------------------===//
85// Test cases.
86//===----------------------------------------------------------------------===//
87
88NSComparisonResult f1(NSString* s) {
89 NSString *aString = 0;
90 return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil.}}
91}
92
93NSComparisonResult f2(NSString* s) {
94 NSString *aString = 0;
95 return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil.}}
96}
97
98NSComparisonResult f3(NSString* s, NSStringCompareOptions op) {
99 NSString *aString = 0;
100 return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil.}}
101}
102
103NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) {
104 NSString *aString = 0;
105 return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil.}}
106}
107
108NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) {
109 NSString *aString = 0;
110 return [s compare:aString options:op range:R locale:0]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil.}}
111}
112
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000113NSArray *f6(NSString* s) {
Ted Kremenek859be3b2008-06-16 20:37:30 +0000114 return [s componentsSeparatedByCharactersInSet:0]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil.}}
115}
116
117NSString* f7(NSString* s1, NSString* s2, NSString* s3) {
118
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000119 NSString* s4 = (NSString*)
Ted Kremenekcf118d42009-02-04 23:49:09 +0000120 CFStringCreateWithFormat(kCFAllocatorDefault, 0, // expected-warning{{leak}}
Daniel Dunbar4489fe12008-08-05 00:07:51 +0000121 (CFStringRef) __builtin___CFStringMakeConstantString("%@ %@ (%@)"),
122 s1, s2, s3);
Ted Kremenek859be3b2008-06-16 20:37:30 +0000123
124 CFRetain(s4);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000125 return s4;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000126}
127
128NSMutableArray* f8() {
129
130 NSString* s = [[NSString alloc] init];
131 NSMutableArray* a = [[NSMutableArray alloc] initWithCapacity:2];
132 [a addObject:s];
133 [s release]; // no-warning
134 return a;
135}
136
137void f9() {
138
139 NSString* s = [[NSString alloc] init];
140 NSString* q = s;
141 [s release];
142 [q release]; // expected-warning {{used after it is released}}
143}
144
145NSString* f10() {
Ted Kremenek859be3b2008-06-16 20:37:30 +0000146 static NSString* s = 0;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000147 if (!s) s = [[NSString alloc] init];
Ted Kremenek859be3b2008-06-16 20:37:30 +0000148 return s; // no-warning
149}
150
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000151// Test case for regression reported in <rdar://problem/6452745>.
152// Essentially 's' should not be considered allocated on the false branch.
153// This exercises the 'EvalAssume' logic in GRTransferFuncs (CFRefCount.cpp).
154NSString* f11(CFDictionaryRef dict, const char* key) {
155 NSString* s = (NSString*) CFDictionaryGetValue(dict, key);
156 [s retain];
157 if (s) {
158 [s release];
159 }
160}
161
Ted Kremenek784606f2008-12-18 23:40:58 +0000162// Test case for passing a tracked object by-reference to a function we
Ted Kremenek09f14192009-04-21 20:01:03 +0000163// don't understand.
Ted Kremenek784606f2008-12-18 23:40:58 +0000164void unknown_function_f12(NSString** s);
165void f12() {
166 NSString *string = [[NSString alloc] init];
167 unknown_function_f12(&string); // no-warning
168}
169
Ted Kremenek09f14192009-04-21 20:01:03 +0000170// Test double release of CFString (PR 4014).
171void f13(void) {
172 CFStringRef ref = CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100);
173 CFRelease(ref);
174 CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}}
175}
Ted Kremenek784606f2008-12-18 23:40:58 +0000176
Ted Kremenek95d3b902009-05-11 15:26:06 +0000177// Test regular use of -autorelease
178@interface TestAutorelease
179-(NSString*) getString;
180@end
181@implementation TestAutorelease
182-(NSString*) getString {
183 NSString *str = [[NSString alloc] init];
184 return [str autorelease]; // no-warning
185}
Ted Kremenek2033a952009-05-13 07:12:33 +0000186- (void)m1
187{
188 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
189 [s retain];
190 [s autorelease];
191}
192- (void)m2
193{
194 NSString *s = [[[NSString alloc] init] autorelease]; // expected-warning{{leak}}
195 [s retain];
196}
197- (void)m3
198{
199 NSString *s = [[[NSString alloc] init] autorelease];
200 [s retain];
201 [s autorelease];
202}
203- (void)m4
204{
205 NSString *s = [[NSString alloc] init]; // expected-warning{{leak}}
206 [s retain];
207}
208- (void)m5
209{
210 NSString *s = [[NSString alloc] init];
211 [s autorelease];
212}
Ted Kremenek95d3b902009-05-11 15:26:06 +0000213@end
214
Ted Kremenek859be3b2008-06-16 20:37:30 +0000215@interface C1 : NSObject {}
216- (NSString*) getShared;
217+ (C1*) sharedInstance;
218@end
Ted Kremenekaeca9632008-07-03 15:37:02 +0000219@implementation C1 : NSObject {}
Ted Kremenek859be3b2008-06-16 20:37:30 +0000220- (NSString*) getShared {
221 static NSString* s = 0;
222 if (!s) s = [[NSString alloc] init];
223 return s; // no-warning
224}
225+ (C1 *)sharedInstance {
226 static C1 *sharedInstance = 0;
227 if (!sharedInstance) {
228 sharedInstance = [[C1 alloc] init];
229 }
230 return sharedInstance; // no-warning
231}
232@end
233
234@interface SharedClass : NSObject
235+ (id)sharedInstance;
Ted Kremenek234a4c22009-01-07 00:39:56 +0000236- (id)notShared;
Ted Kremenek859be3b2008-06-16 20:37:30 +0000237@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000238
Ted Kremenekaeca9632008-07-03 15:37:02 +0000239@implementation SharedClass
Ted Kremenek859be3b2008-06-16 20:37:30 +0000240
241- (id)_init {
242 if ((self = [super init])) {
243 NSLog(@"Bar");
244 }
245 return self;
246}
247
Ted Kremenek234a4c22009-01-07 00:39:56 +0000248- (id)notShared {
Ted Kremenek043254a2009-02-07 22:55:48 +0000249 return [[SharedClass alloc] _init]; // expected-warning{{leak}}
Ted Kremenek234a4c22009-01-07 00:39:56 +0000250}
251
Ted Kremenek859be3b2008-06-16 20:37:30 +0000252+ (id)sharedInstance {
253 static SharedClass *_sharedInstance = 0;
254 if (!_sharedInstance) {
255 _sharedInstance = [[SharedClass alloc] _init];
256 }
257 return _sharedInstance; // no-warning
258}
259@end
Ted Kremenek234a4c22009-01-07 00:39:56 +0000260
261id testSharedClassFromFunction() {
262 return [[SharedClass alloc] _init]; // no-warning
263}
264
Ted Kremenek1670e402009-04-11 00:11:10 +0000265// Test OSCompareAndSwap
266_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
Ted Kremenek98104722009-05-01 17:37:31 +0000267_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000268extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
Ted Kremenek1670e402009-04-11 00:11:10 +0000269
270void testOSCompareAndSwap() {
271 NSString *old = 0;
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000272 NSString *s = [[NSString alloc] init]; // no-warning
Ted Kremenek1670e402009-04-11 00:11:10 +0000273 if (!OSAtomicCompareAndSwapPtr(0, s, (void**) &old))
274 [s release];
275 else
276 [old release];
277}
278
Ted Kremeneka3f45402009-04-29 16:03:59 +0000279void testOSCompareAndSwap32Barrier() {
280 NSString *old = 0;
281 NSString *s = [[NSString alloc] init]; // no-warning
282 if (!OSAtomicCompareAndSwap32Barrier((int32_t) 0, (int32_t) s, (int32_t*) &old))
283 [s release];
284 else
285 [old release];
286}
287
Ted Kremenekb3bf76f2009-04-11 00:54:13 +0000288void test_objc_atomicCompareAndSwap() {
289 NSString *old = 0;
290 NSString *s = [[NSString alloc] init]; // no-warning
291 if (!objc_atomicCompareAndSwapPtr(0, s, &old))
292 [s release];
293 else
294 [old release];
295}
296
Ted Kremeneke87450e2009-04-23 19:11:35 +0000297// Test stringWithFormat (<rdar://problem/6815234>)
298void test_stringWithFormat() {
299 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain];
300 [string release];
Ted Kremenekf9df1362009-04-23 21:25:57 +0000301 [string release]; // expected-warning{{Incorrect decrement of the reference count}}
Ted Kremeneke87450e2009-04-23 19:11:35 +0000302}
303
Ted Kremenek92511432009-05-03 06:08:32 +0000304// Test isTrackedObjectType().
Ted Kremenek97d095f2009-04-23 22:11:07 +0000305typedef NSString* WonkyTypedef;
306@interface TestIsTracked
307+ (WonkyTypedef)newString;
308@end
309
310void test_isTrackedObjectType(void) {
311 NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}}
312}
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000313
Ted Kremenek92511432009-05-03 06:08:32 +0000314// Test isTrackedCFObjectType().
315@interface TestIsCFTracked
316+ (CFStringRef) badNewCFString;
317+ (CFStringRef) newCFString;
318@end
319
320@implementation TestIsCFTracked
321+ (CFStringRef) newCFString {
322 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning
323}
324+ (CFStringRef) badNewCFString {
325 return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}}
326}
327
Ted Kremenekb3b0b362009-05-02 01:49:13 +0000328// Test @synchronized
329void test_synchronized(id x) {
330 @synchronized(x) {
331 NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}}
332 }
333}
334
Ted Kremenek2033a952009-05-13 07:12:33 +0000335