Skip to content

[alpha.webkit.UncountedCallArgsChecker] Allow protector functions in Objective-C++ #108184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 11, 2024

Conversation

rniwa
Copy link
Contributor

@rniwa rniwa commented Sep 11, 2024

This PR fixes the bug that WebKit checkers didn't recognize the return value of an Objective-C++ selector which returns Ref or RefPtr to be safe.

…Objective-C++

This PR fixes the bug that WebKit checkers didn't recognize the return value of
an Objective-C++ selector which returns Ref or RefPtr to be safe.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Sep 11, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2024

@llvm/pr-subscribers-clang-static-analyzer-1

@llvm/pr-subscribers-clang

Author: Ryosuke Niwa (rniwa)

Changes

This PR fixes the bug that WebKit checkers didn't recognize the return value of an Objective-C++ selector which returns Ref or RefPtr to be safe.


Full diff: https://github.com/llvm/llvm-project/pull/108184.diff

4 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp (+11)
  • (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h (+5)
  • (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp (+1-2)
  • (added) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm (+26)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 49bbff1942167b..5a484d0546e95f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -143,6 +143,17 @@ bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
   return false;
 }
 
+std::optional<bool> isUncounted(const clang::QualType T)
+{
+  if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
+    if (auto *Decl = Subst->getAssociatedDecl()) {
+      if (isRefType(safeGetName(Decl)))
+        return false;
+    }
+  }
+  return isUncounted(T->getAsCXXRecordDecl());
+}
+
 std::optional<bool> isUncounted(const CXXRecordDecl* Class)
 {
   // Keep isRefCounted first as it's cheaper.
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index ec1db1cc335807..2932e62ad06e4b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -20,6 +20,7 @@ class CXXMethodDecl;
 class CXXRecordDecl;
 class Decl;
 class FunctionDecl;
+class QualType;
 class Stmt;
 class Type;
 
@@ -42,6 +43,10 @@ std::optional<bool> isRefCountable(const clang::CXXRecordDecl* Class);
 /// \returns true if \p Class is ref-counted, false if not.
 bool isRefCounted(const clang::CXXRecordDecl *Class);
 
+/// \returns true if \p Class is ref-countable AND not ref-counted, false if
+/// not, std::nullopt if inconclusive.
+std::optional<bool> isUncounted(const clang::QualType T);
+
 /// \returns true if \p Class is ref-countable AND not ref-counted, false if
 /// not, std::nullopt if inconclusive.
 std::optional<bool> isUncounted(const clang::CXXRecordDecl* Class);
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
index 704c082a4d1d63..81c2434ce64775 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
@@ -87,8 +87,7 @@ class UncountedCallArgsChecker
         }
         auto *E = MemberCallExpr->getImplicitObjectArgument();
         QualType ArgType = MemberCallExpr->getObjectType();
-        std::optional<bool> IsUncounted =
-            isUncounted(ArgType->getAsCXXRecordDecl());
+        std::optional<bool> IsUncounted = isUncounted(ArgType);
         if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E))
           reportBugOnThis(E);
       }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
new file mode 100644
index 00000000000000..db0c5b19eec5bb
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
@@ -0,0 +1,26 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
+// expected-no-diagnostics
+
+#import "mock-types.h"
+#import "mock-system-header.h"
+#import "../../Inputs/system-header-simulator-for-objc-dealloc.h"
+
+@interface Foo : NSObject
+
+@property (nonatomic, readonly) RefPtr<RefCountable> countable;
+
+- (void)execute;
+- (RefPtr<RefCountable>)_protectedRefCountable;
+@end
+
+@implementation Foo
+
+- (void)execute {
+  self._protectedRefCountable->method();
+}
+
+- (RefPtr<RefCountable>)_protectedRefCountable {
+  return _countable;
+}
+
+@end

Copy link

github-actions bot commented Sep 11, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@rniwa rniwa requested a review from haoNoQ September 11, 2024 16:32
@rniwa rniwa requested a review from haoNoQ September 11, 2024 17:11
Copy link
Collaborator

@haoNoQ haoNoQ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha ok LGTM!

}
return isUncounted(T->getAsCXXRecordDecl());
}

std::optional<bool> isUncounted(const CXXRecordDecl* Class)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we force every checker to use the new function now that we know about this cornercase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the only other place where this function is called is in isUncountedPtr but that function needs to evaluate whether the pointee is ref counted or not so I don't think we can use the new function.

@rniwa
Copy link
Contributor Author

rniwa commented Sep 11, 2024

Thanks for the review!

@rniwa rniwa merged commit b06954a into llvm:main Sep 11, 2024
6 of 8 checks passed
@rniwa rniwa deleted the fix-objc-protected-function branch September 11, 2024 19:06
rniwa added a commit to rniwa/llvm-project that referenced this pull request Feb 3, 2025
…Objective-C++ (llvm#108184)

This PR fixes the bug that WebKit checkers didn't recognize the return
value of an Objective-C++ selector which returns Ref or RefPtr to be
safe.
devincoughlin pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 25, 2025
…Objective-C++ (llvm#108184)

This PR fixes the bug that WebKit checkers didn't recognize the return
value of an Objective-C++ selector which returns Ref or RefPtr to be
safe.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:static analyzer clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants