diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index ba9259a36a873..8e9fff8ac454b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -175,7 +175,8 @@ bool isCtorOfCheckedPtr(const clang::FunctionDecl *F) { bool isCtorOfRetainPtrOrOSPtr(const clang::FunctionDecl *F) { const std::string &FunctionName = safeGetName(F); return FunctionName == "RetainPtr" || FunctionName == "adoptNS" || - FunctionName == "adoptCF" || FunctionName == "retainPtr" || + FunctionName == "adoptNSNullable" || FunctionName == "adoptCF" || + FunctionName == "adoptCFNullable" || FunctionName == "retainPtr" || FunctionName == "RetainPtrArc" || FunctionName == "adoptNSArc" || FunctionName == "adoptOSObject" || FunctionName == "adoptOSObjectArc"; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp index 2af9067f8f808..afa9fc7b1c4a4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp @@ -122,11 +122,13 @@ class RetainPtrCtorAdoptChecker bool isAdoptFnName(const std::string &Name) const { return isAdoptNS(Name) || Name == "adoptCF" || Name == "adoptCFArc" || + Name == "adoptCFNullable" || Name == "adoptCFNullableArc" || Name == "adoptOSObject" || Name == "adoptOSObjectArc"; } bool isAdoptNS(const std::string &Name) const { - return Name == "adoptNS" || Name == "adoptNSArc"; + return Name == "adoptNS" || Name == "adoptNSArc" || + Name == "adoptNSNullable" || Name == "adoptNSNullableArc"; } void visitCallExpr(const CallExpr *CE, const Decl *DeclWithIssue) const { diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h index 124821a8ded55..503d11bea3089 100644 --- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h @@ -265,7 +265,9 @@ void WTFCrash(void); template class RetainPtr; template RetainPtr adoptNS(T*); +template RetainPtr adoptNSNullable(T*); template RetainPtr adoptCF(T); +template RetainPtr adoptCFNullable(T); template T *downcast(S *t) { return static_cast(t); } @@ -367,7 +369,9 @@ template struct RetainPtr { CFTypeRef toCFTypeRef(const void* ptr) { return (CFTypeRef)ptr; } template friend RetainPtr adoptNS(U*); + template friend RetainPtr adoptNSNullable(U*); template friend RetainPtr adoptCF(U); + template friend RetainPtr adoptCFNullable(U); enum AdoptTag { Adopt }; RetainPtr(PtrType t, AdoptTag) : t(t) { } @@ -395,11 +399,25 @@ RetainPtr adoptNS(T* t) { #endif } +template +RetainPtr adoptNSNullable(T* t) { +#if __has_feature(objc_arc) + return t; +#else + return RetainPtr(t, RetainPtr::Adopt); +#endif +} + template RetainPtr adoptCF(T t) { return RetainPtr(t, RetainPtr::Adopt); } +template +RetainPtr adoptCFNullable(T t) { + return RetainPtr(t, RetainPtr::Adopt); +} + template inline RetainPtr retainPtr(T ptr) { return ptr; @@ -681,7 +699,9 @@ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT(CFDictionary, CFMutableDictionary); using WTF::RetainPtr; using WTF::adoptNS; +using WTF::adoptNSNullable; using WTF::adoptCF; +using WTF::adoptCFNullable; using WTF::retainPtr; using WTF::OSObjectPtr; using WTF::adoptOSObject; diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm index 79ea95b088167..135fe651a9f16 100644 --- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm +++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm @@ -12,9 +12,11 @@ void basic_correct() { auto ns4 = adoptNS([ns3 mutableCopy]); auto ns5 = adoptNS([ns3 copyWithValue:3]); auto ns6 = retainPtr([ns3 next]); + auto ns7 = adoptNSNullable([[SomeObj alloc] init]); CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10)); auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault)); auto cf3 = adoptCF(checked_cf_cast(CFCopyArray(cf1))); + auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10)); } CFMutableArrayRef provide_cf(); @@ -24,6 +26,8 @@ void basic_wrong() { // 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]}} auto ns2 = adoptNS([ns1.get() next]); // 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]}} + auto ns3 = adoptNSNullable([ns1.get() next]); + // expected-warning@-1{{Incorrect use of adoptNSNullable. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}} RetainPtr cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10); // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} RetainPtr cf2 = adoptCF(provide_cf()); @@ -32,6 +36,8 @@ void basic_wrong() { // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} CFCopyArray(cf1); // expected-warning@-1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} + RetainPtr cf4 = adoptCFNullable(provide_cf()); + // expected-warning@-1{{Incorrect use of adoptCFNullable. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}} } void basic_correct_arc() { diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm index 20f951b27a149..c337752d6bd21 100644 --- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm +++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm @@ -15,9 +15,11 @@ void basic_correct() { auto ns6 = retainPtr([ns3 next]); auto ns7 = retainPtr((SomeObj *)0); auto ns8 = adoptNS(nil); + auto ns9 = adoptNSNullable([[SomeObj alloc] init]); CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10)); auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault)); auto cf3 = adoptCF(checked_cf_cast(CFCopyArray(cf1))); + auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10)); CreateCopy(); } @@ -28,6 +30,8 @@ void basic_wrong() { // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} auto ns2 = adoptNS([ns1.get() next]); // expected-warning@-1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}} + auto ns3 = adoptNSNullable([ns1.get() next]); + // expected-warning@-1{{Incorrect use of adoptNSNullable. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}} RetainPtr cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10); // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} RetainPtr cf2 = adoptCF(provide_cf()); @@ -36,6 +40,8 @@ void basic_wrong() { // expected-warning@-1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} CFCopyArray(cf1); // expected-warning@-1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}} + RetainPtr cf4 = adoptCFNullable(provide_cf()); + // expected-warning@-1{{Incorrect use of adoptCFNullable. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}} } void basic_correct_arc() { diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm index cfc214fae33e5..add9144744db4 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm @@ -385,7 +385,9 @@ void os_ptr() { namespace call_with_adopt_ref { void foo() { [adoptNS(provide()).get() doWork]; + [adoptNSNullable(provide()).get() doWork]; CFArrayAppendValue(adoptCF(provide_cf()).get(), nullptr); + CFArrayAppendValue(adoptCFNullable(provide_cf()).get(), nullptr); consume_dispatch(adoptOSObject(provide_dispatch()).get()); } }