Author: Ryosuke Niwa Date: 2026-05-27T18:13:30-07:00 New Revision: d65897289e68696fa5f5b2d2f449f7633fff13ab
URL: https://github.com/llvm/llvm-project/commit/d65897289e68696fa5f5b2d2f449f7633fff13ab DIFF: https://github.com/llvm/llvm-project/commit/d65897289e68696fa5f5b2d2f449f7633fff13ab.diff LOG: [alpha.webkit.UncountedLocalVarsChecker] Detect an assignment to a guardian argument (#198695) A function parameter of type RefPtr<T>& should not be used as a guardian variable of a raw pointer/reference variable if the function body contains an assignment to it since such an assignment can shorten the lifetime of the guarded object. Added: Modified: clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp index 442b8ef58688a..56df6742eda9c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp @@ -86,6 +86,8 @@ struct GuardianVisitor : DynamicRecursiveASTVisitor { auto *Callee = CE->getDirectCallee(); if (!Callee) return false; + if (isPtrConversion(Callee)) + return true; unsigned ArgIndex = 0; unsigned ArgOffset = isa<CXXOperatorCallExpr>(CE); for (auto *Arg : CE->arguments()) { @@ -327,13 +329,14 @@ class RawPtrRefLocalVarsChecker std::optional<bool> IsUncountedPtr = isUnsafePtr(V->getType()); if (IsUncountedPtr && *IsUncountedPtr) { - if (isPtrOriginSafe(V, Value)) + if (isPtrOriginSafe(V, Value, DeclWithIssue)) return; reportBug(V, Value, nullptr, DeclWithIssue); } } - bool isPtrOriginSafe(const VarDecl *V, const Expr *Value) const { + bool isPtrOriginSafe(const VarDecl *V, const Expr *Value, + const Decl *DeclWithIssue) const { return tryToFindPtrOrigin( Value, /*StopAtFirstRefCountedObj=*/false, [&](const clang::CXXRecordDecl *Record) { return isSafePtr(Record); }, @@ -378,10 +381,18 @@ class RawPtrRefLocalVarsChecker } } - // Parameters are guaranteed to be safe for the duration of - // the call by another checker. - if (isa<ParmVarDecl>(MaybeGuardian)) - return true; + if (isa<ParmVarDecl>(MaybeGuardian)) { + if (auto *FD = dyn_cast<FunctionDecl>(DeclWithIssue)) { + if (GuardianVisitor{MaybeGuardian}.TraverseStmt( + FD->getBody())) + return true; + } + if (auto *MD = dyn_cast<ObjCMethodDecl>(DeclWithIssue)) { + if (GuardianVisitor{MaybeGuardian}.TraverseStmt( + MD->getBody())) + return true; + } + } } } diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp index 4cb3f560633af..d87e076cb4096 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp @@ -385,6 +385,19 @@ void baz() { } // namespace local_assignment_basic +namespace local_assignment_to_guardian_parameter { + +RefCountable *provide_ref_cntbl(); + +void foo(RefPtr<RefCountable>& arg) { + RefCountable* ptr = arg.get(); + // expected-warning@-1{{Local variable 'ptr' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}} + arg = nullptr; + ptr->method(); +} + +} // namespace local_assignment_to_guardian + namespace local_assignment_to_parameter { RefCountable *provide_ref_cntbl(); diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm index f49e7bdb3e79c..04f403eda206f 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm @@ -594,4 +594,11 @@ - (void)storeSomeObj { auto *obj = [self getSomeObj]; [obj doWork]; } + +- (void)assignToGuardianArg:(RetainPtr<SomeObj>&)obj { + SomeObj* ptr = obj.get(); + // expected-warning@-1{{Local variable 'ptr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}} + obj = nullptr; + [ptr doWork]; +} @end _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
