Skip to content

Commit e5fa38b

Browse files
authored
[WebKit checkers] Treat passing of a member variable which is capable of CheckedPtr as safe. (#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 64bd4d9 commit e5fa38b

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
@@ -236,6 +236,26 @@ bool isConstOwnerPtrMemberExpr(const clang::Expr *E) {
236236
return isOwnerPtrType(T) && T.isConstQualified();
237237
}
238238

239+
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E) {
240+
auto *ME = dyn_cast<MemberExpr>(E);
241+
if (!ME)
242+
return false;
243+
auto *Base = ME->getBase();
244+
if (!Base)
245+
return false;
246+
if (!isa<CXXThisExpr>(Base->IgnoreParenCasts()))
247+
return false;
248+
auto *D = ME->getMemberDecl();
249+
if (!D)
250+
return false;
251+
auto T = D->getType();
252+
auto *CXXRD = T->getAsCXXRecordDecl();
253+
if (!CXXRD)
254+
return false;
255+
auto result = isCheckedPtrCapable(CXXRD);
256+
return result && *result;
257+
}
258+
239259
class EnsureFunctionVisitor
240260
: public ConstStmtVisitor<EnsureFunctionVisitor, bool> {
241261
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
@@ -443,6 +443,10 @@ class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
443443
return isRefOrCheckedPtrType(type);
444444
}
445445

446+
bool isSafeExpr(const Expr *E) const final {
447+
return isExprToGetCheckedPtrCapableMember(E);
448+
}
449+
446450
const char *ptrKind() const final { return "unchecked"; }
447451
};
448452

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,9 @@ class UncheckedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
417417
bool isSafePtrType(const QualType type) const final {
418418
return isRefOrCheckedPtrType(type);
419419
}
420+
bool isSafeExpr(const Expr *E) const final {
421+
return isExprToGetCheckedPtrCapableMember(E);
422+
}
420423
const char *ptrKind() const final { return "unchecked"; }
421424
};
422425

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)