[clang] [alpha.webkit.UnretainedCallArgsChecker] Treat NSStringFromSelector and alike as trivial and returns a retained value (PR #161135)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 15 12:07:35 PDT 2025
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/161135
>From 36c59a97ab7bd58de108213106eca27a2626557d Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Sun, 28 Sep 2025 23:27:44 -0700
Subject: [PATCH] [alpha.webkit.UnretainedCallArgsChecker] Treat
NSStringFromSelector and alike as trivial and returns a retained value
Treat NSStringFromSelector, NSSelectorFromString, NSStringFromClass, NSClassFromString, NSStringFromProtocol, and
NSProtocolFromString as trivial, and treat their return values as a safe pointer origin since the return value of
these functions don't need to be retained.
---
.../Checkers/WebKit/ASTUtils.cpp | 6 +++++-
.../Analysis/Checkers/WebKit/objc-mock-types.h | 10 +++++++++-
.../Checkers/WebKit/unretained-call-args.mm | 18 ++++++++++++++++++
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index c1a5000f8b647..953c9711c9343 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -164,7 +164,9 @@ bool tryToFindPtrOrigin(
auto Name = safeGetName(callee);
if (Name == "__builtin___CFStringMakeConstantString" ||
- Name == "NSClassFromString")
+ Name == "NSStringFromSelector" || Name == "NSSelectorFromString" ||
+ Name == "NSStringFromClass" || Name == "NSClassFromString" ||
+ Name == "NSStringFromProtocol" || Name == "NSProtocolFromString")
return callback(E, true);
} else if (auto *CalleeE = call->getCallee()) {
if (auto *E = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
@@ -202,6 +204,8 @@ bool tryToFindPtrOrigin(
!Selector.getNumArgs())
return callback(E, true);
}
+ if (auto *ObjCProtocol = dyn_cast<ObjCProtocolExpr>(E))
+ return callback(ObjCProtocol, true);
if (auto *ObjCDict = dyn_cast<ObjCDictionaryLiteral>(E))
return callback(ObjCDict, true);
if (auto *ObjCArray = dyn_cast<ObjCArrayLiteral>(E))
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index a5fc3d7f9a932..edf40115afa19 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -98,12 +98,20 @@ typedef CVImageBufferRef CVPixelBufferRef;
typedef signed int CVReturn;
CVReturn CVPixelBufferCreateWithIOSurface(CFAllocatorRef allocator, IOSurfaceRef surface, CFDictionaryRef pixelBufferAttributes, CF_RETURNS_RETAINED CVPixelBufferRef * pixelBufferOut);
+extern "C" NSString *NSStringFromSelector(SEL aSelector);
+extern "C" SEL NSSelectorFromString(NSString *aSelectorName);
+
+extern "C" NSString *NSStringFromClass(Class aClass);
+extern "C" Class NSClassFromString(NSString *aClassName);
+
+extern "C" NSString *NSStringFromProtocol(Protocol *proto);
+extern "C" Protocol * NSProtocolFromString(NSString *namestr);
+
CFRunLoopRef CFRunLoopGetCurrent(void);
CFRunLoopRef CFRunLoopGetMain(void);
extern CFTypeRef CFRetain(CFTypeRef cf);
extern void CFRelease(CFTypeRef cf);
#define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
-extern Class NSClassFromString(NSString *aClassName);
#if __has_feature(objc_arc)
id CFBridgingRelease(CFTypeRef X) {
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index 5dc3b38ccb61c..4f231ee8b1c84 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -578,6 +578,24 @@ void foo() {
} // autoreleased
+namespace sel_string {
+
+void consumeStr(NSString *);
+void consumeSel(SEL);
+void consumeClass(Class);
+void consumeProtocol(Protocol *);
+
+void foo() {
+ consumeStr(NSStringFromSelector(@selector(mutableCopy)));
+ consumeSel(NSSelectorFromString(@"mutableCopy"));
+ consumeStr(NSStringFromClass(NSNumber.class));
+ consumeClass(NSClassFromString(@"NSNumber"));
+ consumeStr(NSStringFromProtocol(@protocol(NSCopying)));
+ consumeProtocol(NSProtocolFromString(@"NSCopying"));
+}
+
+} // namespace sel_string
+
@interface TestObject : NSObject
- (void)doWork:(NSString *)msg, ...;
- (void)doWorkOnSelf;
More information about the cfe-commits
mailing list