Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
20 changes: 20 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ void WTFCrash(void);

template<typename T> class RetainPtr;
template<typename T> RetainPtr<T> adoptNS(T*);
template<typename T> RetainPtr<T> adoptNSNullable(T*);
template<typename T> RetainPtr<T> adoptCF(T);
template<typename T> RetainPtr<T> adoptCFNullable(T);

template <typename T, typename S> T *downcast(S *t) { return static_cast<T*>(t); }

Expand Down Expand Up @@ -367,7 +369,9 @@ template <typename T> struct RetainPtr {
CFTypeRef toCFTypeRef(const void* ptr) { return (CFTypeRef)ptr; }

template <typename U> friend RetainPtr<U> adoptNS(U*);
template <typename U> friend RetainPtr<U> adoptNSNullable(U*);
template <typename U> friend RetainPtr<U> adoptCF(U);
template <typename U> friend RetainPtr<U> adoptCFNullable(U);

enum AdoptTag { Adopt };
RetainPtr(PtrType t, AdoptTag) : t(t) { }
Expand Down Expand Up @@ -395,11 +399,25 @@ RetainPtr<T> adoptNS(T* t) {
#endif
}

template <typename T>
RetainPtr<T> adoptNSNullable(T* t) {
#if __has_feature(objc_arc)
return t;
#else
return RetainPtr<T>(t, RetainPtr<T>::Adopt);
#endif
}

template <typename T>
RetainPtr<T> adoptCF(T t) {
return RetainPtr<T>(t, RetainPtr<T>::Adopt);
}

template <typename T>
RetainPtr<T> adoptCFNullable(T t) {
return RetainPtr<T>(t, RetainPtr<T>::Adopt);
}

template<typename T> inline RetainPtr<T> retainPtr(T ptr)
{
return ptr;
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<CFArrayRef>(CFCopyArray(cf1)));
auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10));
}

CFMutableArrayRef provide_cf();
Expand All @@ -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<CFMutableArrayRef> 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<CFMutableArrayRef> cf2 = adoptCF(provide_cf());
Expand All @@ -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<CFMutableArrayRef> 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<CFArrayRef>(CFCopyArray(cf1)));
auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10));
CreateCopy();
}

Expand All @@ -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<CFMutableArrayRef> 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<CFMutableArrayRef> cf2 = adoptCF(provide_cf());
Expand All @@ -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<CFMutableArrayRef> 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() {
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand Down