[analyzer] Check for NULL passed to CFAutorelease.
Patch by Sean McBride, tests adjusted by me. llvm-svn: 211453
This commit is contained in:
parent
002c25602c
commit
e3f310f3bd
|
@ -523,16 +523,17 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
|
|||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CFRetain/CFRelease/CFMakeCollectable checking for null arguments.
|
||||
// CFRetain/CFRelease/CFMakeCollectable/CFAutorelease checking for null arguments.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class CFRetainReleaseChecker : public Checker< check::PreStmt<CallExpr> > {
|
||||
mutable std::unique_ptr<APIMisuse> BT;
|
||||
mutable IdentifierInfo *Retain, *Release, *MakeCollectable;
|
||||
mutable IdentifierInfo *Retain, *Release, *MakeCollectable, *Autorelease;
|
||||
public:
|
||||
CFRetainReleaseChecker()
|
||||
: Retain(nullptr), Release(nullptr), MakeCollectable(nullptr) {}
|
||||
: Retain(nullptr), Release(nullptr), MakeCollectable(nullptr),
|
||||
Autorelease(nullptr) {}
|
||||
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
@ -554,13 +555,15 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
|||
Retain = &Ctx.Idents.get("CFRetain");
|
||||
Release = &Ctx.Idents.get("CFRelease");
|
||||
MakeCollectable = &Ctx.Idents.get("CFMakeCollectable");
|
||||
Autorelease = &Ctx.Idents.get("CFAutorelease");
|
||||
BT.reset(new APIMisuse(
|
||||
this, "null passed to CFRetain/CFRelease/CFMakeCollectable"));
|
||||
this, "null passed to CF memory management function"));
|
||||
}
|
||||
|
||||
// Check if we called CFRetain/CFRelease/CFMakeCollectable.
|
||||
// Check if we called CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
const IdentifierInfo *FuncII = FD->getIdentifier();
|
||||
if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable))
|
||||
if (!(FuncII == Retain || FuncII == Release || FuncII == MakeCollectable ||
|
||||
FuncII == Autorelease))
|
||||
return;
|
||||
|
||||
// FIXME: The rest of this just checks that the argument is non-null.
|
||||
|
@ -597,6 +600,8 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
|||
description = "Null pointer argument in call to CFRelease";
|
||||
else if (FuncII == MakeCollectable)
|
||||
description = "Null pointer argument in call to CFMakeCollectable";
|
||||
else if (FuncII == Autorelease)
|
||||
description = "Null pointer argument in call to CFAutorelease";
|
||||
else
|
||||
llvm_unreachable("impossible case");
|
||||
|
||||
|
|
|
@ -528,38 +528,54 @@ void f15() {
|
|||
CFRelease(*B); // no-warning
|
||||
}
|
||||
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f16(int x, CFTypeRef p) {
|
||||
if (p)
|
||||
return;
|
||||
|
||||
if (x > 0) {
|
||||
CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
|
||||
}
|
||||
else if (x < 0) {
|
||||
CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
|
||||
}
|
||||
else {
|
||||
CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p);
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p);
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p);
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Test that an object is non-null after being CFRetained/CFReleased.
|
||||
// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f17(int x, CFTypeRef p) {
|
||||
if (x > 0) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p);
|
||||
if (!p)
|
||||
CFRelease(0); // no-warning
|
||||
}
|
||||
else if (x < 0) {
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p);
|
||||
if (!p)
|
||||
CFRetain(0); // no-warning
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p);
|
||||
if (!p)
|
||||
CFMakeCollectable(0); // no-warning
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p);
|
||||
if (!p)
|
||||
CFAutorelease(0); // no-warning
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -570,38 +570,54 @@ void f15() {
|
|||
CFRelease(*B); // no-warning
|
||||
}
|
||||
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f16(int x, CFTypeRef p) {
|
||||
if (p)
|
||||
return;
|
||||
|
||||
if (x > 0) {
|
||||
CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
|
||||
}
|
||||
else if (x < 0) {
|
||||
CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
|
||||
}
|
||||
else {
|
||||
CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p);
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p);
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p);
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Test that an object is non-null after being CFRetained/CFReleased.
|
||||
// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f17(int x, CFTypeRef p) {
|
||||
if (x > 0) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p);
|
||||
if (!p)
|
||||
CFRelease(0); // no-warning
|
||||
}
|
||||
else if (x < 0) {
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p);
|
||||
if (!p)
|
||||
CFRetain(0); // no-warning
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p);
|
||||
if (!p)
|
||||
CFMakeCollectable(0); // no-warning
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p);
|
||||
if (!p)
|
||||
CFAutorelease(0); // no-warning
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -542,7 +542,7 @@ static void CreateRefUndef(SCDynamicStoreRef *storeRef, unsigned x) {
|
|||
// CHECK-NEXT: </array>
|
||||
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
|
||||
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
|
||||
// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string>
|
||||
// CHECK-NEXT: <key>issue_context</key><string>test</string>
|
||||
// CHECK-NEXT: <key>issue_hash</key><string>5</string>
|
||||
|
|
|
@ -523,38 +523,54 @@ void f15() {
|
|||
CFRelease(*B); // no-warning
|
||||
}
|
||||
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable.
|
||||
// Test when we pass NULL to CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f16(int x, CFTypeRef p) {
|
||||
if (p)
|
||||
return;
|
||||
|
||||
if (x > 0) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p); // expected-warning{{Null pointer argument in call to CFRelease}}
|
||||
}
|
||||
else if (x < 0) {
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p); // expected-warning{{Null pointer argument in call to CFRetain}}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p); // expected-warning{{Null pointer argument in call to CFMakeCollectable}}
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p); // expected-warning{{Null pointer argument in call to CFAutorelease}}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Test that an object is non-null after being CFRetained/CFReleased.
|
||||
// Test that an object is non-null after CFRetain/CFRelease/CFMakeCollectable/CFAutorelease.
|
||||
void f17(int x, CFTypeRef p) {
|
||||
if (x > 0) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
CFRelease(p);
|
||||
if (!p)
|
||||
CFRelease(0); // no-warning
|
||||
}
|
||||
else if (x < 0) {
|
||||
break;
|
||||
case 1:
|
||||
CFRetain(p);
|
||||
if (!p)
|
||||
CFRetain(0); // no-warning
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case 2:
|
||||
CFMakeCollectable(p);
|
||||
if (!p)
|
||||
CFMakeCollectable(0); // no-warning
|
||||
break;
|
||||
case 3:
|
||||
CFAutorelease(p);
|
||||
if (!p)
|
||||
CFAutorelease(0); // no-warning
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9501,7 +9517,7 @@ id returnNSNull() {
|
|||
// CHECK-NEXT: </array>
|
||||
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRelease</string>
|
||||
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
|
||||
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
|
||||
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
|
||||
// CHECK-NEXT: <key>issue_hash</key><string>5</string>
|
||||
|
@ -9838,7 +9854,7 @@ id returnNSNull() {
|
|||
// CHECK-NEXT: </array>
|
||||
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFRetain</string>
|
||||
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
|
||||
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
|
||||
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
|
||||
// CHECK-NEXT: <key>issue_hash</key><string>8</string>
|
||||
|
@ -10175,7 +10191,7 @@ id returnNSNull() {
|
|||
// CHECK-NEXT: </array>
|
||||
// CHECK-NEXT: <key>description</key><string>Null pointer argument in call to CFMakeCollectable</string>
|
||||
// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CFRetain/CFRelease/CFMakeCollectable</string>
|
||||
// CHECK-NEXT: <key>type</key><string>null passed to CF memory management function</string>
|
||||
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
|
||||
// CHECK-NEXT: <key>issue_context</key><string>f16</string>
|
||||
// CHECK-NEXT: <key>issue_hash</key><string>11</string>
|
||||
|
|
Loading…
Reference in New Issue