NSString.m revision cf118d41f7930a18dce97416ef7834a62642f587
1// RUN: clang -analyze -checker-cfref -analyzer-store-basic -verify %s && 2// RUN: clang -analyze -checker-cfref -analyzer-store-region -verify %s 3 4//===----------------------------------------------------------------------===// 5// The following code is reduced using delta-debugging from 6// Foundation.h (Mac OS X). 7// 8// It includes the basic definitions for the test cases below. 9// Not directly including Foundation.h directly makes this test case 10// both svelte and portable to non-Mac platforms. 11//===----------------------------------------------------------------------===// 12 13typedef const void * CFTypeRef; 14typedef const struct __CFString * CFStringRef; 15typedef const struct __CFAllocator * CFAllocatorRef; 16extern const CFAllocatorRef kCFAllocatorDefault; 17extern CFTypeRef CFRetain(CFTypeRef cf); 18typedef const struct __CFDictionary * CFDictionaryRef; 19const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key); 20extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...); 21typedef signed char BOOL; 22typedef int NSInteger; 23typedef unsigned int NSUInteger; 24@class NSString, Protocol; 25extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); 26typedef NSInteger NSComparisonResult; 27typedef struct _NSZone NSZone; 28@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 29@protocol NSObject 30- (BOOL)isEqual:(id)object; 31- (oneway void)release; 32- (id)retain; 33@end 34@protocol NSCopying 35- (id)copyWithZone:(NSZone *)zone; 36@end 37@protocol NSMutableCopying 38- (id)mutableCopyWithZone:(NSZone *)zone; 39@end 40@protocol NSCoding 41- (void)encodeWithCoder:(NSCoder *)aCoder; 42@end 43@interface NSObject <NSObject> {} 44- (id)init; 45+ (id)alloc; 46@end 47extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); 48typedef struct {} NSFastEnumerationState; 49@protocol NSFastEnumeration 50- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 51@end 52@class NSString; 53typedef struct _NSRange {} NSRange; 54@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> 55- (NSUInteger)count; 56@end 57@interface NSMutableArray : NSArray 58- (void)addObject:(id)anObject; 59- (id)initWithCapacity:(NSUInteger)numItems; 60@end 61typedef unsigned short unichar; 62@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale; 63typedef NSUInteger NSStringCompareOptions; 64@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; 65- (NSComparisonResult)compare:(NSString *)string; 66- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask; 67- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange; 68- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale; 69- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string; 70- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator; 71@end 72@interface NSSimpleCString : NSString {} @end 73@interface NSConstantString : NSSimpleCString @end 74extern void *_NSConstantStringClassReference; 75 76//===----------------------------------------------------------------------===// 77// Test cases. 78//===----------------------------------------------------------------------===// 79 80NSComparisonResult f1(NSString* s) { 81 NSString *aString = 0; 82 return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil.}} 83} 84 85NSComparisonResult f2(NSString* s) { 86 NSString *aString = 0; 87 return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil.}} 88} 89 90NSComparisonResult f3(NSString* s, NSStringCompareOptions op) { 91 NSString *aString = 0; 92 return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil.}} 93} 94 95NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) { 96 NSString *aString = 0; 97 return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil.}} 98} 99 100NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) { 101 NSString *aString = 0; 102 return [s compare:aString options:op range:R locale:0]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil.}} 103} 104 105NSArray *f6(NSString* s) { 106 return [s componentsSeparatedByCharactersInSet:0]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil.}} 107} 108 109NSString* f7(NSString* s1, NSString* s2, NSString* s3) { 110 111 NSString* s4 = (NSString*) 112 CFStringCreateWithFormat(kCFAllocatorDefault, 0, // expected-warning{{leak}} 113 (CFStringRef) __builtin___CFStringMakeConstantString("%@ %@ (%@)"), 114 s1, s2, s3); 115 116 CFRetain(s4); 117 return s4; 118} 119 120NSMutableArray* f8() { 121 122 NSString* s = [[NSString alloc] init]; 123 NSMutableArray* a = [[NSMutableArray alloc] initWithCapacity:2]; 124 [a addObject:s]; 125 [s release]; // no-warning 126 return a; 127} 128 129void f9() { 130 131 NSString* s = [[NSString alloc] init]; 132 NSString* q = s; 133 [s release]; 134 [q release]; // expected-warning {{used after it is released}} 135} 136 137NSString* f10() { 138 static NSString* s = 0; 139 if (!s) s = [[NSString alloc] init]; 140 return s; // no-warning 141} 142 143// Test case for regression reported in <rdar://problem/6452745>. 144// Essentially 's' should not be considered allocated on the false branch. 145// This exercises the 'EvalAssume' logic in GRTransferFuncs (CFRefCount.cpp). 146NSString* f11(CFDictionaryRef dict, const char* key) { 147 NSString* s = (NSString*) CFDictionaryGetValue(dict, key); 148 [s retain]; 149 if (s) { 150 [s release]; 151 } 152} 153 154// Test case for passing a tracked object by-reference to a function we 155// don't undersand. 156void unknown_function_f12(NSString** s); 157void f12() { 158 NSString *string = [[NSString alloc] init]; 159 unknown_function_f12(&string); // no-warning 160} 161 162 163@interface C1 : NSObject {} 164- (NSString*) getShared; 165+ (C1*) sharedInstance; 166@end 167@implementation C1 : NSObject {} 168- (NSString*) getShared { 169 static NSString* s = 0; 170 if (!s) s = [[NSString alloc] init]; 171 return s; // no-warning 172} 173+ (C1 *)sharedInstance { 174 static C1 *sharedInstance = 0; 175 if (!sharedInstance) { 176 sharedInstance = [[C1 alloc] init]; 177 } 178 return sharedInstance; // no-warning 179} 180@end 181 182@interface SharedClass : NSObject 183+ (id)sharedInstance; 184- (id)notShared; 185@end 186 187@implementation SharedClass 188 189- (id)_init { 190 if ((self = [super init])) { 191 NSLog(@"Bar"); 192 } 193 return self; 194} 195 196- (id)notShared { 197 return [[SharedClass alloc] _init]; // expected-warning{{[naming convention] leak of returned object}} 198} 199 200+ (id)sharedInstance { 201 static SharedClass *_sharedInstance = 0; 202 if (!_sharedInstance) { 203 _sharedInstance = [[SharedClass alloc] _init]; 204 } 205 return _sharedInstance; // no-warning 206} 207@end 208 209id testSharedClassFromFunction() { 210 return [[SharedClass alloc] _init]; // no-warning 211} 212 213