retain-release.m revision 79b4f7d37530a1c41df26b6ac3a159f7cd6388d6
1//>>SLICER 2// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && 3// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-old-cast -verify %s && 4// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s 5 6//===----------------------------------------------------------------------===// 7// The following code is reduced using delta-debugging from Mac OS X headers: 8// 9// #include <Cocoa/Cocoa.h> 10// #include <CoreFoundation/CoreFoundation.h> 11// #include <DiskArbitration/DiskArbitration.h> 12// #include <QuartzCore/QuartzCore.h> 13// #include <Quartz/Quartz.h> 14// #include <IOKit/IOKitLib.h> 15// 16// It includes the basic definitions for the test cases below. 17//===----------------------------------------------------------------------===// 18 19typedef unsigned int __darwin_natural_t; 20typedef unsigned long uintptr_t; 21typedef unsigned int uint32_t; 22typedef unsigned long long uint64_t; 23typedef unsigned int UInt32; 24typedef signed long CFIndex; 25typedef const void * CFTypeRef; 26typedef const struct __CFString * CFStringRef; 27typedef const struct __CFAllocator * CFAllocatorRef; 28extern const CFAllocatorRef kCFAllocatorDefault; 29extern CFTypeRef CFRetain(CFTypeRef cf); 30extern void CFRelease(CFTypeRef cf); 31typedef struct { 32} 33CFArrayCallBacks; 34extern const CFArrayCallBacks kCFTypeArrayCallBacks; 35typedef const struct __CFArray * CFArrayRef; 36typedef struct __CFArray * CFMutableArrayRef; 37extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); 38extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); 39extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); 40typedef const struct __CFDictionary * CFDictionaryRef; 41typedef struct __CFDictionary * CFMutableDictionaryRef; 42typedef UInt32 CFStringEncoding; 43enum { 44kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; 45extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); 46typedef double CFTimeInterval; 47typedef CFTimeInterval CFAbsoluteTime; 48extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); 49typedef const struct __CFDate * CFDateRef; 50extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); 51extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); 52typedef __darwin_natural_t natural_t; 53typedef natural_t mach_port_name_t; 54typedef mach_port_name_t mach_port_t; 55typedef int kern_return_t; 56typedef kern_return_t mach_error_t; 57typedef signed char BOOL; 58typedef unsigned long NSUInteger; 59@class NSString, Protocol; 60extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); 61typedef struct _NSZone NSZone; 62@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 63@protocol NSObject - (BOOL)isEqual:(id)object; 64- (id)retain; 65- (oneway void)release; 66- (id)autorelease; 67@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; 68@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 69@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 70@end @interface NSObject <NSObject> { 71} 72+ (id)allocWithZone:(NSZone *)zone; 73+ (id)alloc; 74- (void)dealloc; 75@end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); 76typedef struct { 77} 78NSFastEnumerationState; 79@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 80@end @class NSString; 81@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 82@end @interface NSArray (NSArrayCreation) + (id)array; 83@end @interface NSAutoreleasePool : NSObject { 84} 85- (void)drain; 86@end extern NSString * const NSBundleDidLoadNotification; 87typedef double NSTimeInterval; 88@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; 89@end typedef unsigned short unichar; 90@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; 91- ( const char *)UTF8String; 92- (id)initWithUTF8String:(const char *)nullTerminatedCString; 93+ (id)stringWithUTF8String:(const char *)nullTerminatedCString; 94@end @class NSString, NSData; 95@interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; 96+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length; 97+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b; 98@end @class NSString; 99@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 100@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; 101- (void)setObject:(id)anObject forKey:(id)aKey; 102@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems; 103@end typedef double CGFloat; 104struct CGSize { 105}; 106typedef struct CGSize CGSize; 107struct CGRect { 108}; 109typedef struct CGRect CGRect; 110@protocol NSLocking - (void)lock; 111- (id)init; 112@end @class NSURLAuthenticationChallenge; 113typedef mach_port_t io_object_t; 114typedef char io_name_t[128]; 115typedef io_object_t io_iterator_t; 116typedef io_object_t io_service_t; 117typedef struct IONotificationPort * IONotificationPortRef; 118typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator ); 119io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ); 120kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); 121kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated)); 122kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification ); 123CFMutableDictionaryRef IOServiceMatching( const char * name ); 124CFMutableDictionaryRef IOServiceNameMatching( const char * name ); 125CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName ); 126CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path ); 127CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID ); 128typedef struct __DASession * DASessionRef; 129extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); 130typedef struct __DADisk * DADiskRef; 131extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); 132extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); 133extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); 134extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); 135typedef struct CGColorSpace *CGColorSpaceRef; 136typedef struct CGImage *CGImageRef; 137 typedef struct CGLayer *CGLayerRef; 138 @class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow; 139@interface NSResponder : NSObject <NSCoding> { 140} 141@end @protocol NSAnimatablePropertyContainer - (id)animator; 142@end extern NSString *NSAnimationTriggerOrderIn ; 143@interface NSView : NSResponder <NSAnimatablePropertyContainer> { 144struct __VFlags2 { 145} 146_vFlags2; 147} 148@end extern NSString * const NSFullScreenModeAllScreens; 149@protocol NSChangeSpelling - (void)changeSpelling:(id)sender; 150@end @protocol NSIgnoreMisspelledWords - (void)ignoreSpelling:(id)sender; 151@end @class NSColor, NSFont, NSNotification; 152@interface NSText : NSView <NSChangeSpelling, NSIgnoreMisspelledWords> { 153} 154@end @protocol NSValidatedUserInterfaceItem - (SEL)action; 155@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem; 156@end @class NSArray, NSError, NSImage, NSView, NSNotificationCenter, NSURL, NSScreen, NSRunningApplication; 157@interface NSApplication : NSResponder <NSUserInterfaceValidations> { 158} 159@end enum { 160NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 }; 161typedef NSUInteger NSApplicationTerminateReply; 162@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; 163@end enum { 164} 165_CFlags; 166@interface CIImage : NSObject <NSCoding, NSCopying> { 167} 168typedef int CIFormat; 169@end enum { 170kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; 171typedef mach_error_t DAReturn; 172typedef const struct __DADissenter * DADissenterRef; 173extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); 174@interface CIContext: NSObject { 175} 176- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r; 177- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs; 178- (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d; 179@end @class NSURL; 180@protocol QCCompositionRenderer - (NSDictionary*) attributes; 181@end @interface QCRenderer : NSObject <QCCompositionRenderer> { 182} 183- (id) createSnapshotImageOfType:(NSString*)type; 184@end extern NSString* const QCViewDidStartRenderingNotification; 185@interface QCView : NSView <QCCompositionRenderer> { 186} 187- (id) createSnapshotImageOfType:(NSString*)type; 188@end enum { 189ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, }; 190@class ICDevice; 191@protocol ICDeviceDelegate <NSObject> @required - (void)didRemoveDevice:(ICDevice*)device; 192@end @class ICCameraDevice; 193@class ICScannerDevice; 194@protocol ICScannerDeviceDelegate <ICDeviceDelegate> @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner; 195@end 196 197//===----------------------------------------------------------------------===// 198// Test cases. 199//===----------------------------------------------------------------------===// 200 201CFAbsoluteTime f1() { 202 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 203 CFDateRef date = CFDateCreate(0, t); 204 CFRetain(date); 205 CFRelease(date); 206 CFDateGetAbsoluteTime(date); // no-warning 207 CFRelease(date); 208 t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} 209 return t; 210} 211 212CFAbsoluteTime f2() { 213 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 214 CFDateRef date = CFDateCreate(0, t); 215 [((NSDate*) date) retain]; 216 CFRelease(date); 217 CFDateGetAbsoluteTime(date); // no-warning 218 [((NSDate*) date) release]; 219 t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} 220 return t; 221} 222 223 224NSDate* global_x; 225 226// Test to see if we supresss an error when we store the pointer 227// to a global. 228 229CFAbsoluteTime f3() { 230 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 231 CFDateRef date = CFDateCreate(0, t); 232 [((NSDate*) date) retain]; 233 CFRelease(date); 234 CFDateGetAbsoluteTime(date); // no-warning 235 global_x = (NSDate*) date; 236 [((NSDate*) date) release]; 237 t = CFDateGetAbsoluteTime(date); // no-warning 238 return t; 239} 240 241//--------------------------------------------------------------------------- 242// Test case 'f4' differs for region store and basic store. See 243// retain-release-region-store.m and retain-release-basic-store.m. 244//--------------------------------------------------------------------------- 245 246// Test a leak. 247 248CFAbsoluteTime f5(int x) { 249 CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 250 CFDateRef date = CFDateCreate(0, t); // expected-warning{{leak}} 251 252 if (x) 253 CFRelease(date); 254 255 return t; 256} 257 258// Test a leak involving the return. 259 260CFDateRef f6(int x) { 261 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning{{leak}} 262 CFRetain(date); 263 return date; 264} 265 266// Test a leak involving an overwrite. 267 268CFDateRef f7() { 269 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); //expected-warning{{leak}} 270 CFRetain(date); 271 date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 272 return date; 273} 274 275// Generalization of Create rule. MyDateCreate returns a CFXXXTypeRef, and 276// has the word create. 277CFDateRef MyDateCreate(); 278 279CFDateRef f8() { 280 CFDateRef date = MyDateCreate(); // expected-warning{{leak}} 281 CFRetain(date); 282 return date; 283} 284 285CFDateRef f9() { 286 CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 287 int *p = 0; 288 // When allocations fail, CFDateCreate can return null. 289 if (!date) *p = 1; // expected-warning{{null}} 290 return date; 291} 292 293// Handle DiskArbitration API: 294// 295// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/DiscArbitrationFramework/ 296// 297void f10(io_service_t media, DADiskRef d, CFStringRef s) { 298 DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, 0, "hello"); // expected-warning{{leak}} 299 if (disk) NSLog(@"ok"); 300 301 disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, 0, media); // expected-warning{{leak}} 302 if (disk) NSLog(@"ok"); 303 304 CFDictionaryRef dict = DADiskCopyDescription(d); // expected-warning{{leak}} 305 if (dict) NSLog(@"ok"); 306 307 disk = DADiskCopyWholeDisk(d); // expected-warning{{leak}} 308 if (disk) NSLog(@"ok"); 309 310 DADissenterRef dissenter = DADissenterCreate(kCFAllocatorDefault, // expected-warning{{leak}} 311 kDAReturnSuccess, s); 312 if (dissenter) NSLog(@"ok"); 313 314 DASessionRef session = DASessionCreate(kCFAllocatorDefault); // expected-warning{{leak}} 315 if (session) NSLog(@"ok"); 316} 317 318// Test retain/release checker with CFString and CFMutableArray. 319void f11() { 320 // Create the array. 321 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 322 323 // Create a string. 324 CFStringRef s1 = CFStringCreateWithCString(0, "hello world", 325 kCFStringEncodingUTF8); 326 327 // Add the string to the array. 328 CFArrayAppendValue(A, s1); 329 330 // Decrement the reference count. 331 CFRelease(s1); // no-warning 332 333 // Get the string. We don't own it. 334 s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0); 335 336 // Release the array. 337 CFRelease(A); // no-warning 338 339 // Release the string. This is a bug. 340 CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}} 341} 342 343// PR 3337: Handle functions declared using typedefs. 344typedef CFTypeRef CREATEFUN(); 345CREATEFUN MyCreateFun; 346 347void f12() { 348 CFTypeRef o = MyCreateFun(); // expected-warning {{leak}} 349} 350 351void f13_autorelease() { 352 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning 353 [(id) A autorelease]; // no-warning 354} 355 356void f13_autorelease_b() { 357 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 358 [(id) A autorelease]; 359 [(id) A autorelease]; // expected-warning{{Object sent -autorelease too many times}} 360} 361 362CFMutableArrayRef f13_autorelease_c() { 363 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 364 [(id) A autorelease]; 365 [(id) A autorelease]; 366 return A; // expected-warning{{Object sent -autorelease too many times}} 367} 368 369CFMutableArrayRef f13_autorelease_d() { 370 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 371 [(id) A autorelease]; 372 [(id) A autorelease]; 373 CFMutableArrayRef B = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{Object sent -autorelease too many times}} 374 CFRelease(B); // no-warning 375} 376 377 378// This case exercises the logic where the leak site is the same as the allocation site. 379void f14_leakimmediately() { 380 CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}} 381} 382 383// Test that we track an allocated object beyond the point where the *name* 384// of the variable storing the reference is no longer live. 385void f15() { 386 // Create the array. 387 CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); 388 CFMutableArrayRef *B = &A; 389 // At this point, the name 'A' is no longer live. 390 CFRelease(*B); // no-warning 391} 392 393// Test when we pass NULL to CFRetain/CFRelease. 394void f16(int x, CFTypeRef p) { 395 if (p) 396 return; 397 398 if (x) { 399 CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}} 400 } 401 else { 402 CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}} 403 } 404} 405 406// Test basic tracking of ivars associated with 'self'. For the retain/release 407// checker we currently do not want to flag leaks associated with stores 408// of tracked objects to ivars. 409@interface SelfIvarTest : NSObject { 410 id myObj; 411} 412- (void)test_self_tracking; 413@end 414 415@implementation SelfIvarTest 416- (void)test_self_tracking { 417 myObj = (id) CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning 418} 419@end 420 421// Test return of non-owned objects in contexts where an owned object 422// is expected. 423@interface TestReturnNotOwnedWhenExpectedOwned 424- (NSString*)newString; 425@end 426 427@implementation TestReturnNotOwnedWhenExpectedOwned 428- (NSString*)newString { 429 NSString *s = [NSString stringWithUTF8String:"hello"]; 430 return s; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} 431} 432@end 433 434// <rdar://problem/6659160> 435int isFoo(char c); 436 437static void rdar_6659160(char *inkind, char *inname) 438{ 439 // We currently expect that [NSObject alloc] cannot fail. This 440 // will be a toggled flag in the future. It can indeed return null, but 441 // Cocoa programmers generally aren't expected to reason about out-of-memory 442 // conditions. 443 NSString *kind = [[NSString alloc] initWithUTF8String:inkind]; // expected-warning{{leak}} 444 445 // We do allow stringWithUTF8String to fail. This isn't really correct, as 446 // far as returning 0. In most error conditions it will throw an exception. 447 // If allocation fails it could return 0, but again this 448 // isn't expected. 449 NSString *name = [NSString stringWithUTF8String:inname]; 450 if(!name) 451 return; 452 453 const char *kindC = 0; 454 const char *nameC = 0; 455 456 // In both cases, we cannot reach a point down below where we 457 // dereference kindC or nameC with either being null. This is because 458 // we assume that [NSObject alloc] doesn't fail and that we have the guard 459 // up above. 460 461 if(kind) 462 kindC = [kind UTF8String]; 463 if(name) 464 nameC = [name UTF8String]; 465 if(!isFoo(kindC[0])) // expected-warning{{null}} 466 return; 467 if(!isFoo(nameC[0])) // no-warning 468 return; 469 470 [kind release]; 471 [name release]; // expected-warning{{Incorrect decrement of the reference count}} 472} 473 474// PR 3677 - 'allocWithZone' should be treated as following the Cocoa naming 475// conventions with respect to 'return'ing ownership. 476@interface PR3677: NSObject @end 477@implementation PR3677 478+ (id)allocWithZone:(NSZone *)inZone { 479 return [super allocWithZone:inZone]; // no-warning 480} 481@end 482 483// PR 3820 - Reason about calls to -dealloc 484void pr3820_DeallocInsteadOfRelease(void) 485{ 486 id foo = [[NSString alloc] init]; // no-warning 487 [foo dealloc]; 488 // foo is not leaked, since it has been deallocated. 489} 490 491void pr3820_ReleaseAfterDealloc(void) 492{ 493 id foo = [[NSString alloc] init]; 494 [foo dealloc]; 495 [foo release]; // expected-warning{{used after it is release}} 496 // NSInternalInconsistencyException: message sent to deallocated object 497} 498 499void pr3820_DeallocAfterRelease(void) 500{ 501 NSLog(@"\n\n[%s]", __FUNCTION__); 502 id foo = [[NSString alloc] init]; 503 [foo release]; 504 [foo dealloc]; // expected-warning{{used after it is released}} 505 // message sent to released object 506} 507 508// From <rdar://problem/6704930>. The problem here is that 'length' binds to 509// '($0 - 1)' after '--length', but SimpleConstraintManager doesn't know how to 510// reason about '($0 - 1) > constant'. As a temporary hack, we drop the value 511// of '($0 - 1)' and conjure a new symbol. 512void rdar6704930(unsigned char *s, unsigned int length) { 513 NSString* name = 0; 514 if (s != 0) { 515 if (length > 0) { 516 while (length > 0) { 517 if (*s == ':') { 518 ++s; 519 --length; 520 name = [[NSString alloc] init]; // no-warning 521 break; 522 } 523 ++s; 524 --length; 525 } 526 if ((length == 0) && (name != 0)) { 527 [name release]; 528 name = 0; 529 } 530 if (length == 0) { // no ':' found -> use it all as name 531 name = [[NSString alloc] init]; // no-warning 532 } 533 } 534 } 535 536 if (name != 0) { 537 [name release]; 538 } 539} 540 541//===----------------------------------------------------------------------===// 542// <rdar://problem/6833332> 543// One build of the analyzer accidentally stopped tracking the allocated 544// object after the 'retain'. 545//===----------------------------------------------------------------------===// 546 547@interface rdar_6833332 : NSObject <NSApplicationDelegate> { 548 NSWindow *window; 549} 550@property (nonatomic, retain) NSWindow *window; 551@end 552 553@implementation rdar_6833332 554@synthesize window; 555- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 556 NSMutableDictionary *dict = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; // expected-warning{{leak}} 557 558 [dict setObject:@"foo" forKey:@"bar"]; 559 560 NSLog(@"%@", dict); 561} 562- (void)dealloc { 563 [window release]; 564 [super dealloc]; 565} 566@end 567 568//===----------------------------------------------------------------------===// 569// <rdar://problem/6257780> clang checker fails to catch use-after-release 570//===----------------------------------------------------------------------===// 571 572int rdar_6257780_Case1() { 573 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 574 NSArray *array = [NSArray array]; 575 [array release]; // expected-warning{{Incorrect decrement of the reference count of an object is not owned at this point by the caller}} 576 [pool drain]; 577 return 0; 578} 579 580//===----------------------------------------------------------------------===// 581// <rdar://problem/6866843> Checker should understand new/setObject:/release constructs 582//===----------------------------------------------------------------------===// 583 584void rdar_6866843() { 585 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 586 NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init]; 587 NSArray* array = [[NSArray alloc] init]; 588 [dictionary setObject:array forKey:@"key"]; 589 [array release]; 590 // Using 'array' here should be fine 591 NSLog(@"array = %@\n", array); // no-warning 592 // Now the array is released 593 [dictionary release]; 594 [pool drain]; 595} 596 597 598//===----------------------------------------------------------------------===// 599// <rdar://problem/6877235> Classes typedef-ed to CF objects should get the same treatment as CF objects 600//===----------------------------------------------------------------------===// 601 602typedef CFTypeRef OtherRef; 603 604@interface RDar6877235 : NSObject {} 605- (CFTypeRef)_copyCFTypeRef; 606- (OtherRef)_copyOtherRef; 607@end 608 609@implementation RDar6877235 610- (CFTypeRef)_copyCFTypeRef { 611 return [[NSString alloc] init]; // no-warning 612} 613- (OtherRef)_copyOtherRef { 614 return [[NSString alloc] init]; // no-warning 615} 616@end 617 618//===----------------------------------------------------------------------===// 619//<rdar://problem/6320065> false positive - init method returns an object owned by caller 620//===----------------------------------------------------------------------===// 621 622@interface RDar6320065 : NSObject { 623 NSString *_foo; 624} 625- (id)initReturningNewClass; 626- (id)initReturningNewClassBad; 627- (id)initReturningNewClassBad2; 628@end 629 630@interface RDar6320065Subclass : RDar6320065 631@end 632 633@implementation RDar6320065 634- (id)initReturningNewClass { 635 [self release]; 636 self = [[RDar6320065Subclass alloc] init]; // no-warning 637 return self; 638} 639- (id)initReturningNewClassBad { 640 [self release]; 641 [[RDar6320065Subclass alloc] init]; // expected-warning {{leak}} 642 return self; 643} 644- (id)initReturningNewClassBad2 { 645 [self release]; 646 self = [[RDar6320065Subclass alloc] init]; 647 return [self autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} 648} 649 650@end 651 652@implementation RDar6320065Subclass 653@end 654 655int RDar6320065_test() { 656 RDar6320065 *test = [[RDar6320065 alloc] init]; // no-warning 657 [test release]; 658 return 0; 659} 660 661//===----------------------------------------------------------------------===// 662// <rdar://problem/6859457> [NSData dataWithBytesNoCopy] does not return a retained object 663//===----------------------------------------------------------------------===// 664 665@interface RDar6859457 : NSObject {} 666- (NSString*) NoCopyString; 667- (NSString*) noCopyString; 668@end 669 670@implementation RDar6859457 671- (NSString*) NoCopyString { return [[NSString alloc] init]; } // no-warning 672- (NSString*) noCopyString { return [[NSString alloc] init]; } // no-warning 673@end 674 675void test_RDar6859457(RDar6859457 *x, void *bytes, NSUInteger dataLength) { 676 [x NoCopyString]; // expected-warning{{leak}} 677 [x noCopyString]; // expected-warning{{leak}} 678 [NSData dataWithBytesNoCopy:bytes length:dataLength]; // no-warning 679 [NSData dataWithBytesNoCopy:bytes length:dataLength freeWhenDone:1]; // no-warning 680} 681 682//===----------------------------------------------------------------------===// 683// PR 4230 - an autorelease pool is not necessarily leaked during a premature 684// return 685//===----------------------------------------------------------------------===// 686 687static void PR4230(void) 688{ 689 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // no-warning 690 NSString *object = [[[NSString alloc] init] autorelease]; // no-warning 691 return; 692} 693 694//===----------------------------------------------------------------------===// 695// Method name that has a null IdentifierInfo* for its first selector slot. 696// This test just makes sure that we handle it. 697//===----------------------------------------------------------------------===// 698 699@interface TestNullIdentifier 700@end 701 702@implementation TestNullIdentifier 703+ (id):(int)x, ... { 704 return [[NSString alloc] init]; // expected-warning{{leak}} 705} 706@end 707 708//===----------------------------------------------------------------------===// 709// <rdar://problem/6893565> don't flag leaks for return types that cannot be 710// determined to be CF types 711//===----------------------------------------------------------------------===// 712 713// We don't know if 'struct s6893565' represents a Core Foundation type, so 714// we shouldn't emit an error here. 715typedef struct s6893565* TD6893565; 716 717@interface RDar6893565 {} 718-(TD6893565)newThing; 719@end 720 721@implementation RDar6893565 722-(TD6893565)newThing { 723 return (TD6893565) [[NSString alloc] init]; // no-warning 724} 725@end 726 727//===----------------------------------------------------------------------===// 728// <rdar://problem/6902710> clang: false positives w/QC and CoreImage methods 729//===----------------------------------------------------------------------===// 730 731void rdar6902710(QCView *view, QCRenderer *renderer, CIContext *context, 732 NSString *str, CIImage *img, CGRect rect, 733 CIFormat form, CGColorSpaceRef cs) { 734 [view createSnapshotImageOfType:str]; // expected-warning{{leak}} 735 [renderer createSnapshotImageOfType:str]; // expected-warning{{leak}} 736 [context createCGImage:img fromRect:rect]; // expected-warning{{leak}} 737 [context createCGImage:img fromRect:rect format:form colorSpace:cs]; // expected-warning{{leak}} 738} 739 740//===----------------------------------------------------------------------===// 741// <rdar://problem/6945561> -[CIContext createCGLayerWithSize:info:] 742// misinterpreted by clang scan-build 743//===----------------------------------------------------------------------===// 744 745void rdar6945561(CIContext *context, CGSize size, CFDictionaryRef d) { 746 [context createCGLayerWithSize:size info:d]; // expected-warning{{leak}} 747} 748 749//===----------------------------------------------------------------------===// 750// <rdar://problem/6961230> add knowledge of IOKit functions to retain/release 751// checker 752//===----------------------------------------------------------------------===// 753 754void IOBSDNameMatching_wrapper(mach_port_t masterPort, uint32_t options, const char * bsdName) { 755 IOBSDNameMatching(masterPort, options, bsdName); // expected-warning{{leak}} 756} 757 758void IOServiceMatching_wrapper(const char * name) { 759 IOServiceMatching(name); // expected-warning{{leak}} 760} 761 762void IOServiceNameMatching_wrapper(const char * name) { 763 IOServiceNameMatching(name); // expected-warning{{leak}} 764} 765 766__attribute__((cf_returns_retained)) CFDictionaryRef CreateDict(); 767 768void IOServiceAddNotification_wrapper(mach_port_t masterPort, const io_name_t notificationType, 769 mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) { 770 771 CFDictionaryRef matching = CreateDict(); 772 CFRelease(matching); 773 IOServiceAddNotification(masterPort, notificationType, matching, // expected-warning{{used after it is released}} expected-warning{{deprecated}} 774 wakePort, reference, notification); 775} 776 777void IORegistryEntryIDMatching_wrapper(uint64_t entryID ) { 778 IORegistryEntryIDMatching(entryID); // expected-warning{{leak}} 779} 780 781void IOOpenFirmwarePathMatching_wrapper(mach_port_t masterPort, uint32_t options, 782 const char * path) { 783 IOOpenFirmwarePathMatching(masterPort, options, path); // expected-warning{{leak}} 784} 785 786void IOServiceGetMatchingService_wrapper(mach_port_t masterPort) { 787 CFDictionaryRef matching = CreateDict(); 788 IOServiceGetMatchingService(masterPort, matching); 789 CFRelease(matching); // expected-warning{{used after it is released}} 790} 791 792void IOServiceGetMatchingServices_wrapper(mach_port_t masterPort, io_iterator_t *existing) { 793 CFDictionaryRef matching = CreateDict(); 794 IOServiceGetMatchingServices(masterPort, matching, existing); 795 CFRelease(matching); // expected-warning{{used after it is released}} 796} 797 798void IOServiceAddMatchingNotification_wrapper(IONotificationPortRef notifyPort, const io_name_t notificationType, 799 IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification) { 800 801 CFDictionaryRef matching = CreateDict(); 802 IOServiceAddMatchingNotification(notifyPort, notificationType, matching, callback, refCon, notification); 803 CFRelease(matching); // expected-warning{{used after it is released}} 804} 805 806//===----------------------------------------------------------------------===// 807// Tests of ownership attributes. 808//===----------------------------------------------------------------------===// 809 810typedef NSString* MyStringTy; 811 812@interface TestOwnershipAttr : NSObject 813- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained)); // no-warning 814- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained)); // no-warning 815- (MyStringTy) returnsAnOwnedTypedString __attribute__((ns_returns_retained)); // no-warning 816- (int) returnsAnOwnedInt __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}} 817@end 818 819static int ownership_attribute_doesnt_go_here __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to function or method types}} 820 821void test_attr_1(TestOwnershipAttr *X) { 822 NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} 823} 824 825void test_attr_1b(TestOwnershipAttr *X) { 826 NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} 827} 828 829@interface MyClassTestCFAttr : NSObject {} 830- (NSDate*) returnsCFRetained __attribute__((cf_returns_retained)); 831- (CFDateRef) returnsCFRetainedAsCF __attribute__((cf_returns_retained)); 832- (NSDate*) alsoReturnsRetained; 833- (CFDateRef) alsoReturnsRetainedAsCF; 834- (NSDate*) returnsNSRetained __attribute__((ns_returns_retained)); 835@end 836 837__attribute__((cf_returns_retained)) 838CFDateRef returnsRetainedCFDate() { 839 return CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 840} 841 842@implementation MyClassTestCFAttr 843- (NSDate*) returnsCFRetained { 844 return (NSDate*) returnsRetainedCFDate(); // No leak. 845} 846 847- (CFDateRef) returnsCFRetainedAsCF { 848 return returnsRetainedCFDate(); // No leak. 849} 850 851 852- (NSDate*) alsoReturnsRetained { 853 return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}} 854} 855 856- (CFDateRef) alsoReturnsRetainedAsCF { 857 return returnsRetainedCFDate(); // expected-warning{{leak}} 858} 859 860 861- (NSDate*) returnsNSRetained { 862 return (NSDate*) returnsRetainedCFDate(); // no-warning 863} 864@end 865 866 867 868