312 lines · plain
1// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}}2// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.RetainPtrCtorAdoptChecker -fobjc-arc -verify %s3 4#include "objc-mock-types.h"5 6CFTypeRef CFCopyArray(CFArrayRef);7 8void basic_correct() {9 auto ns1 = adoptNS([SomeObj alloc]);10 auto ns2 = adoptNS([[SomeObj alloc] init]);11 RetainPtr<SomeObj> ns3 = [ns1.get() next];12 auto ns4 = adoptNS([ns3 mutableCopy]);13 auto ns5 = adoptNS([ns3 copyWithValue:3]);14 auto ns6 = retainPtr([ns3 next]);15 CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));16 auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault));17 auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1)));18}19 20CFMutableArrayRef provide_cf();21 22void basic_wrong() {23 RetainPtr<SomeObj> ns1 = [[SomeObj alloc] init];24 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}25 auto ns2 = adoptNS([ns1.get() next]);26 // expected-warning@-1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}27 RetainPtr<CFMutableArrayRef> cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10);28 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}29 RetainPtr<CFMutableArrayRef> cf2 = adoptCF(provide_cf());30 // expected-warning@-1{{Incorrect use of adoptCF. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}31 RetainPtr<CFTypeRef> cf3 = SecTaskCreateFromSelf(kCFAllocatorDefault);32 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}33 CFCopyArray(cf1);34 // expected-warning@-1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}35}36 37void basic_correct_arc() {38 auto *obj = [[SomeObj alloc] init];39 [obj doWork];40}41 42@implementation SomeObj {43 NSNumber *_number;44 SomeObj *_next;45 SomeObj *_other;46}47 48- (instancetype)_init {49 self = [super init];50 _number = nil;51 _next = nil;52 _other = nil;53 return self;54}55 56- (SomeObj *)mutableCopy {57 auto *copy = [[SomeObj alloc] init];58 [copy setValue:_number];59 [copy setNext:_next];60 [copy setOther:_other];61 return copy;62}63 64- (SomeObj *)copyWithValue:(int)value {65 auto *copy = [[SomeObj alloc] init];66 [copy setValue:_number];67 [copy setNext:_next];68 [copy setOther:_other];69 return copy;70}71 72- (void)doWork {73 _number = [[NSNumber alloc] initWithInt:5];74}75 76- (SomeObj *)other {77 return _other;78}79 80- (void)setOther:(SomeObj *)obj {81 _other = obj;82}83 84- (SomeObj *)next {85 return _next;86}87 88- (void)setNext:(SomeObj *)obj {89 _next = obj;90}91 92- (int)value {93 return [_number intValue];94}95 96- (void)setValue:(NSNumber *)value {97 _number = value;98}99 100@end;101 102RetainPtr<CVPixelBufferRef> cf_out_argument() {103 auto surface = adoptCF(IOSurfaceCreate(nullptr));104 CVPixelBufferRef rawBuffer = nullptr;105 auto status = CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, surface.get(), nullptr, &rawBuffer);106 return adoptCF(rawBuffer);107}108 109RetainPtr<SomeObj> return_nullptr() {110 return nullptr;111}112 113RetainPtr<SomeObj> return_retainptr() {114 RetainPtr<SomeObj> foo;115 return foo;116}117 118CFTypeRef CopyValueForSomething();119 120void cast_retainptr() {121 RetainPtr<NSObject> foo;122 RetainPtr<SomeObj> bar = static_cast<SomeObj*>(foo);123 124 auto baz = adoptCF(CopyValueForSomething()).get();125 RetainPtr<CFArrayRef> v = static_cast<CFArrayRef>(baz);126}127 128CFTypeRef CopyWrapper() {129 return CopyValueForSomething();130}131 132CFTypeRef LeakWrapper() {133 return CopyValueForSomething();134 // expected-warning@-1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}135}136 137NSArray *makeArray() NS_RETURNS_RETAINED {138 return CFBridgingRelease(CFArrayCreateMutable(kCFAllocatorDefault, 10));139}140 141extern Class (*getNSArrayClass)();142NSArray *allocArrayInstance() NS_RETURNS_RETAINED {143 return [[getNSArrayClass() alloc] init];144}145 146extern int (*GetObj)(CF_RETURNS_RETAINED CFTypeRef* objOut);147RetainPtr<CFTypeRef> getObject() {148 CFTypeRef obj = nullptr;149 if (GetObj(&obj))150 return nullptr;151 return adoptCF(obj);152}153 154CFArrayRef CreateSingleArray(CFStringRef);155CFArrayRef CreateSingleArray(CFDictionaryRef);156CFArrayRef CreateSingleArray(CFArrayRef);157template <typename ElementType>158static RetainPtr<CFArrayRef> makeArrayWithSingleEntry(ElementType arg) {159 return adoptCF(CreateSingleArray(arg));160}161 162void callMakeArayWithSingleEntry() {163 auto dictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0));164 makeArrayWithSingleEntry(dictionary.get());165}166 167SomeObj* allocSomeObj() CF_RETURNS_RETAINED;168 169void adopt_retainptr() {170 RetainPtr<NSObject> foo = adoptNS([[SomeObj alloc] init]);171 auto bar = adoptNS([allocSomeObj() init]);172}173 174RetainPtr<CFArrayRef> return_arg(CFArrayRef arg) {175 return arg;176}177 178class MemberInit {179public:180 MemberInit(RetainPtr<CFMutableArrayRef>&& array, NSString *str, CFRunLoopRef runLoop)181 : m_array(array)182 , m_str(str)183 , m_runLoop(runLoop)184 { }185 186private:187 RetainPtr<CFMutableArrayRef> m_array;188 RetainPtr<NSString> m_str;189 RetainPtr<CFRunLoopRef> m_runLoop;190};191void create_member_init() {192 MemberInit init { adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10)), @"hello", CFRunLoopGetCurrent() };193}194 195RetainPtr<CFStringRef> cfstr() {196 return CFSTR("");197}198 199template <typename CF, typename NS>200static RetainPtr<NS> bridge_cast(RetainPtr<CF>&& ptr)201{202 return adoptNS((__bridge NSArray *)(ptr.leakRef()));203}204 205RetainPtr<CFArrayRef> create_cf_array();206RetainPtr<id> return_bridge_cast() {207 return bridge_cast<CFArrayRef, NSArray>(create_cf_array());208}209 210void mutable_copy_dictionary() {211 RetainPtr<NSMutableDictionary> mutableDictionary = adoptNS(@{212 @"Content-Type": @"text/html",213 }.mutableCopy);214}215 216void mutable_copy_array() {217 RetainPtr<NSMutableArray> mutableArray = adoptNS(@[218 @"foo",219 ].mutableCopy);220}221 222void string_copy(NSString *str) {223 RetainPtr<NSString> copy = adoptNS(str.copy);224}225 226void alloc_init_spi() {227 auto ptr = adoptNS([[SomeObj alloc] _init]);228}229 230void alloc_init_c_function() {231 RetainPtr ptr = adoptNS([allocSomeObj() init]);232}233 234CFArrayRef make_array() CF_RETURNS_RETAINED;235 236RetainPtr<CFArrayRef> adopt_make_array() {237 return adoptCF(make_array());238}239 240@interface SomeObject : NSObject241-(void)basic_correct;242-(void)basic_wrong;243-(NSString *)leak_string;244-(NSString *)make_string NS_RETURNS_RETAINED;245@property (nonatomic, readonly) SomeObj *obj;246@end247 248@implementation SomeObject249-(void)basic_correct {250 auto ns1 = adoptNS([SomeObj alloc]);251 auto ns2 = adoptNS([[SomeObj alloc] init]);252 RetainPtr<SomeObj> ns3 = [ns1.get() next];253 auto ns4 = adoptNS([ns3 mutableCopy]);254 auto ns5 = adoptNS([ns3 copyWithValue:3]);255 auto ns6 = retainPtr([ns3 next]);256 CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));257 auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault));258 auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1)));259}260 261-(void)basic_wrong {262 RetainPtr<SomeObj> ns1 = [[SomeObj alloc] init];263 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}264 auto ns2 = adoptNS([ns1.get() next]);265 // expected-warning@-1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}266 RetainPtr<CFMutableArrayRef> cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10);267 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}268 RetainPtr<CFMutableArrayRef> cf2 = adoptCF(provide_cf());269 // expected-warning@-1{{Incorrect use of adoptCF. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}270 RetainPtr<CFTypeRef> cf3 = SecTaskCreateFromSelf(kCFAllocatorDefault);271 // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}272 CFCopyArray(cf1);273 // expected-warning@-1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}274}275 276-(NSString *)leak_string {277 return [[NSString alloc] initWithUTF8String:"hello"];278}279 280-(NSString *)make_string {281 return [[NSString alloc] initWithUTF8String:"hello"];282}283 284-(void)local_leak_string {285 if ([[NSString alloc] initWithUTF8String:"hello"]) {286 }287}288 289-(void)make_some_obj {290 auto some_obj = adoptNS([allocSomeObj() init]);291}292 293-(void)alloc_init_bad_order {294 auto *obj = [NSObject alloc];295 auto ptr = adoptNS([obj init]);296 // expected-warning@-1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}297}298 299-(void)alloc_init_good_order {300 auto obj = adoptNS([NSObject alloc]);301 (void)[obj init];302}303 304-(void)copy_assign_ivar {305 _obj = [allocSomeObj() init];306}307 308-(void)do_more_work:(OtherObj *)otherObj {309 [otherObj doMoreWork:[[OtherObj alloc] init]];310}311@end312