[WebKit checkers] Treat NULL, 0, and nil like nullptr (#157700) This PR makes WebKit checkers treat NULL, 0, and nil like nullptr in various places. GitOrigin-RevId: db74eae1dc92719fe91e0101d8255427933a61d5
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 0d2294e..9a7f5b7 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -217,6 +217,16 @@ return isa<CXXThisExpr>(E); } +bool isNullPtr(const clang::Expr *E) { + if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) + return true; + if (auto *Int = dyn_cast_or_null<IntegerLiteral>(E)) { + if (Int->getValue().isZero()) + return true; + } + return false; +} + bool isConstOwnerPtrMemberExpr(const clang::Expr *E) { if (auto *MCE = dyn_cast<CXXMemberCallExpr>(E)) { if (auto *Callee = MCE->getDirectCallee()) { @@ -275,7 +285,7 @@ bool VisitReturnStmt(const ReturnStmt *RS) { if (auto *RV = RS->getRetValue()) { RV = RV->IgnoreParenCasts(); - if (isa<CXXNullPtrLiteralExpr>(RV)) + if (isNullPtr(RV)) return true; return isConstOwnerPtrMemberExpr(RV); }
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h index 8302bbe..3a009d6 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h +++ b/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h
@@ -66,6 +66,9 @@ /// \returns Whether \p E is a safe call arugment. bool isASafeCallArg(const clang::Expr *E); +/// \returns true if E is nullptr or __null. +bool isNullPtr(const clang::Expr *E); + /// \returns true if E is a MemberExpr accessing a const smart pointer type. bool isConstOwnerPtrMemberExpr(const clang::Expr *E);
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp index ec0c2c1..9deb184 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/WebKit/ForwardDeclChecker.cpp
@@ -272,7 +272,7 @@ ArgExpr = ArgExpr->IgnoreParenCasts(); } } - if (isa<CXXNullPtrLiteralExpr>(ArgExpr) || isa<IntegerLiteral>(ArgExpr) || + if (isNullPtr(ArgExpr) || isa<IntegerLiteral>(ArgExpr) || isa<CXXDefaultArgExpr>(ArgExpr)) return; if (auto *DRE = dyn_cast<DeclRefExpr>(ArgExpr)) {
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp index 764e2c6..e80f174 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp
@@ -217,13 +217,11 @@ [&](const clang::Expr *ArgOrigin, bool IsSafe) { if (IsSafe) return true; - if (isa<CXXNullPtrLiteralExpr>(ArgOrigin)) { - // foo(nullptr) + if (isNullPtr(ArgOrigin)) return true; - } if (isa<IntegerLiteral>(ArgOrigin)) { // FIXME: Check the value. - // foo(NULL) + // foo(123) return true; } if (isa<ObjCStringLiteral>(ArgOrigin))
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp index 7cd86a6..f4f6e28 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp
@@ -295,7 +295,7 @@ if (isa<CXXThisExpr>(InitArgOrigin)) return true; - if (isa<CXXNullPtrLiteralExpr>(InitArgOrigin)) + if (isNullPtr(InitArgOrigin)) return true; if (isa<IntegerLiteral>(InitArgOrigin))
diff --git a/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp index d74fec2..5c1b2d7 100644 --- a/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -177,7 +177,8 @@ CreateOrCopyFnCall.insert(Arg); // Avoid double reporting. return; } - if (Result == IsOwnedResult::Owned || Result == IsOwnedResult::Skip) { + if (Result == IsOwnedResult::Owned || Result == IsOwnedResult::Skip || + isNullPtr(Arg)) { CreateOrCopyFnCall.insert(Arg); return; } @@ -486,7 +487,7 @@ continue; } } - if (isa<CXXNullPtrLiteralExpr>(E)) + if (isNullPtr(E)) return IsOwnedResult::NotOwned; if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { auto QT = DRE->getType();
diff --git a/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp b/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp index f709560..7959daf 100644 --- a/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp +++ b/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp
@@ -71,12 +71,21 @@ return m_obj5.get(); } + CheckedObj* ensureObj6() { + if (!m_obj6) + const_cast<std::unique_ptr<CheckedObj>&>(m_obj6) = new CheckedObj; + if (m_obj6->next()) + return (CheckedObj *)0; + return m_obj6.get(); + } + private: const std::unique_ptr<CheckedObj> m_obj1; std::unique_ptr<CheckedObj> m_obj2; const std::unique_ptr<CheckedObj> m_obj3; const std::unique_ptr<CheckedObj> m_obj4; const std::unique_ptr<CheckedObj> m_obj5; + const std::unique_ptr<CheckedObj> m_obj6; }; void Foo::bar() { @@ -87,6 +96,7 @@ badEnsureObj4().method(); // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}} ensureObj5()->method(); + ensureObj6()->method(); } } // namespace call_args_const_unique_ptr
diff --git a/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm index 83c87b1..7699017 100644 --- a/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm +++ b/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
@@ -13,6 +13,8 @@ auto ns4 = adoptNS([ns3 mutableCopy]); auto ns5 = adoptNS([ns3 copyWithValue:3]); auto ns6 = retainPtr([ns3 next]); + auto ns7 = retainPtr((SomeObj *)0); + auto ns8 = adoptNS(nil); CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10)); auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault)); auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1))); @@ -111,6 +113,10 @@ return adoptCF(rawBuffer); } +RetainPtr<SomeObj> return_nil() { + return nil; +} + RetainPtr<SomeObj> return_nullptr() { return nullptr; }
diff --git a/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp index 0540ed9..3364637 100644 --- a/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp +++ b/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
@@ -121,6 +121,7 @@ RefCountable *bar = foo->trivial() ? foo.get() : nullptr; // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}} foo = nullptr; + foo = (RefCountable *)0; bar->method(); } }
diff --git a/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/test/Analysis/Checkers/WebKit/unretained-call-args.mm index c69113c..3feecd9 100644 --- a/test/Analysis/Checkers/WebKit/unretained-call-args.mm +++ b/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -456,6 +456,8 @@ // expected-warning@-1{{Call argument is unretained and unsafe}} // expected-warning@-2{{Call argument is unretained and unsafe}} [self doWork:@"hello", RetainPtr<SomeObj> { provide() }.get(), RetainPtr<CFMutableArrayRef> { provide_cf() }.get()]; + [self doWork:__null]; + [self doWork:nil]; } - (SomeObj *)getSomeObj {