Skip to content

Commit 79282da

Browse files
committed
[WebKit checkers] Treat passing of a member variable which is capable of CheckedPtr as safe. (llvm#142485)
It's safe for a member function of a class or struct to call a function or allocate a local variable with a pointer or a reference to a member variable since "this" pointer, and therefore all its members, will be kept alive by its caller so recognize as such.
1 parent 35d8ed8 commit 79282da

File tree

6 files changed

+73
-0
lines changed

6 files changed

+73
-0
lines changed

clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,26 @@ bool isConstOwnerPtrMemberExpr(const clang::Expr *E) {
237237
return isOwnerPtrType(T) && T.isConstQualified();
238238
}
239239

240+
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E) {
241+
auto *ME = dyn_cast<MemberExpr>(E);
242+
if (!ME)
243+
return false;
244+
auto *Base = ME->getBase();
245+
if (!Base)
246+
return false;
247+
if (!isa<CXXThisExpr>(Base->IgnoreParenCasts()))
248+
return false;
249+
auto *D = ME->getMemberDecl();
250+
if (!D)
251+
return false;
252+
auto T = D->getType();
253+
auto *CXXRD = T->getAsCXXRecordDecl();
254+
if (!CXXRD)
255+
return false;
256+
auto result = isCheckedPtrCapable(CXXRD);
257+
return result && *result;
258+
}
259+
240260
class EnsureFunctionVisitor
241261
: public ConstStmtVisitor<EnsureFunctionVisitor, bool> {
242262
public:

clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ bool isASafeCallArg(const clang::Expr *E);
6969
/// \returns true if E is a MemberExpr accessing a const smart pointer type.
7070
bool isConstOwnerPtrMemberExpr(const clang::Expr *E);
7171

72+
/// \returns true if E is a MemberExpr accessing a member variable which
73+
/// supports CheckedPtr.
74+
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E);
75+
7276
/// \returns true if E is a CXXMemberCallExpr which returns a const smart
7377
/// pointer type.
7478
class EnsureFunctionAnalysis {

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
448448
return isRefOrCheckedPtrType(type);
449449
}
450450

451+
bool isSafeExpr(const Expr *E) const final {
452+
return isExprToGetCheckedPtrCapableMember(E);
453+
}
454+
451455
const char *ptrKind() const final { return "unchecked"; }
452456
};
453457

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ class UncheckedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
423423
bool isSafePtrType(const QualType type) const final {
424424
return isRefOrCheckedPtrType(type);
425425
}
426+
bool isSafeExpr(const Expr *E) const final {
427+
return isExprToGetCheckedPtrCapableMember(E);
428+
}
426429
const char *ptrKind() const final { return "unchecked"; }
427430
};
428431

clang/test/Analysis/Checkers/WebKit/call-args-checked.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ static void baz() {
4646

4747
} // namespace call_args_checked
4848

49+
namespace call_args_member {
50+
51+
void consume(CheckedObj&);
52+
53+
struct WrapperObj {
54+
CheckedObj checked;
55+
CheckedObj& checkedRef;
56+
void foo() {
57+
consume(checked);
58+
consume(checkedRef);
59+
// expected-warning@-1{{Call argument is unchecked and unsafe [alpha.webkit.UncheckedCallArgsChecker]}}
60+
}
61+
void bar(WrapperObj& other) {
62+
consume(other.checked);
63+
// expected-warning@-1{{Call argument is unchecked and unsafe [alpha.webkit.UncheckedCallArgsChecker]}}
64+
}
65+
};
66+
67+
} // namespace call_args_checked
68+
4969
namespace call_args_default {
5070

5171
void someFunction(RefCountableAndCheckable* = makeObj());

clang/test/Analysis/Checkers/WebKit/unchecked-local-vars.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,28 @@ void foo() {
290290

291291
} // namespace local_assignment_to_global
292292

293+
namespace member_var {
294+
295+
struct WrapperObj {
296+
CheckedObj checked;
297+
CheckedObj& checkedRef;
298+
void foo() {
299+
auto *a = &checked;
300+
a->method();
301+
auto *b = &checkedRef;
302+
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
303+
b->method();
304+
}
305+
306+
void bar(WrapperObj& wrapper) {
307+
CheckedObj* ptr = &wrapper.checked;
308+
// expected-warning@-1{{Local variable 'ptr' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
309+
ptr->method();
310+
}
311+
};
312+
313+
}
314+
293315
namespace local_refcountable_checkable_object {
294316

295317
RefCountableAndCheckable* provide_obj();

0 commit comments

Comments
 (0)