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