Skip to content

Commit cdf2a52

Browse files
Merge pull request #10038 from rniwa/webkit
Merge Webkit checker fixes
2 parents 0e7ec03 + f811649 commit cdf2a52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4362
-243
lines changed

clang/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,10 @@ AST Matchers
13671367
- Fixed captureVars assertion failure if not capturesVariables. (#GH76425)
13681368
- ``forCallable`` now properly preserves binding on successful match. (#GH89657)
13691369

1370+
- Ensure ``hasType`` and ``hasDeclaration`` match Objective-C interface declarations.
1371+
1372+
- Ensure ``pointee`` matches Objective-C pointer types.
1373+
13701374
clang-format
13711375
------------
13721376

clang/docs/analyzer/checkers.rst

+94-5
Original file line numberDiff line numberDiff line change
@@ -3433,6 +3433,52 @@ Check for non-determinism caused by sorting of pointers.
34333433
alpha.WebKit
34343434
^^^^^^^^^^^^
34353435
3436+
.. _alpha-webkit-NoUncheckedPtrMemberChecker:
3437+
3438+
alpha.webkit.MemoryUnsafeCastChecker
3439+
""""""""""""""""""""""""""""""""""""""
3440+
Check for all casts from a base type to its derived type as these might be memory-unsafe.
3441+
3442+
Example:
3443+
3444+
.. code-block:: cpp
3445+
3446+
class Base { };
3447+
class Derived : public Base { };
3448+
3449+
void f(Base* base) {
3450+
Derived* derived = static_cast<Derived*>(base); // ERROR
3451+
}
3452+
3453+
For all cast operations (C-style casts, static_cast, reinterpret_cast, dynamic_cast), if the source type a `Base*` and the destination type is `Derived*`, where `Derived` inherits from `Base`, the static analyzer should signal an error.
3454+
3455+
This applies to:
3456+
3457+
- C structs, C++ structs and classes, and Objective-C classes and protocols.
3458+
- Pointers and references.
3459+
- Inside template instantiations and macro expansions that are visible to the compiler.
3460+
3461+
For types like this, instead of using built in casts, the programmer will use helper functions that internally perform the appropriate type check and disable static analysis.
3462+
3463+
alpha.webkit.NoUncheckedPtrMemberChecker
3464+
""""""""""""""""""""""""""""""""""""""""
3465+
Raw pointers and references to an object which supports CheckedPtr or CheckedRef can't be used as class members. Only CheckedPtr, CheckedRef, RefPtr, or Ref are allowed.
3466+
3467+
.. code-block:: cpp
3468+
3469+
struct CheckableObj {
3470+
void incrementCheckedPtrCount() {}
3471+
void decrementCheckedPtrCount() {}
3472+
};
3473+
3474+
struct Foo {
3475+
CheckableObj* ptr; // warn
3476+
CheckableObj& ptr; // warn
3477+
// ...
3478+
};
3479+
3480+
See `WebKit Guidelines for Safer C++ Programming <https://github.com/WebKit/WebKit/wiki/Safer-CPP-Guidelines>`_ for details.
3481+
34363482
.. _alpha-webkit-UncountedCallArgsChecker:
34373483
34383484
alpha.webkit.UncountedCallArgsChecker
@@ -3522,6 +3568,12 @@ We also define a set of safe transformations which if passed a safe value as an
35223568
- casts
35233569
- unary operators like ``&`` or ``*``
35243570
3571+
alpha.webkit.UncheckedCallArgsChecker
3572+
"""""""""""""""""""""""""""""""""""""
3573+
The goal of this rule is to make sure that lifetime of any dynamically allocated CheckedPtr capable object passed as a call argument keeps its memory region past the end of the call. This applies to call to any function, method, lambda, function pointer or functor. CheckedPtr capable objects aren't supposed to be allocated on stack so we check arguments for parameters of raw pointers and references to unchecked types.
3574+
3575+
The rules of when to use and not to use CheckedPtr / CheckedRef are same as alpha.webkit.UncountedCallArgsChecker for ref-counted objects.
3576+
35253577
alpha.webkit.UncountedLocalVarsChecker
35263578
""""""""""""""""""""""""""""""""""""""
35273579
The goal of this rule is to make sure that any uncounted local variable is backed by a ref-counted object with lifetime that is strictly larger than the scope of the uncounted local variable. To be on the safe side we require the scope of an uncounted variable to be embedded in the scope of ref-counted object that backs it.
@@ -3546,7 +3598,7 @@ These are examples of cases that we consider safe:
35463598
RefCountable* uncounted = this; // ok
35473599
}
35483600
3549-
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that an argument is safe or it's considered if not a bug then bug-prone.
3601+
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that a local variable is safe or it's considered unsafe.
35503602
35513603
.. code-block:: cpp
35523604
@@ -3565,11 +3617,48 @@ Here are some examples of situations that we warn about as they *might* be poten
35653617
RefCountable* uncounted = counted.get(); // warn
35663618
}
35673619
3568-
We don't warn about these cases - we don't consider them necessarily safe but since they are very common and usually safe we'd introduce a lot of false positives otherwise:
3569-
- variable defined in condition part of an ```if``` statement
3570-
- variable defined in init statement condition of a ```for``` statement
3620+
alpha.webkit.UncheckedLocalVarsChecker
3621+
""""""""""""""""""""""""""""""""""""""
3622+
The goal of this rule is to make sure that any unchecked local variable is backed by a CheckedPtr or CheckedRef with lifetime that is strictly larger than the scope of the unchecked local variable. To be on the safe side we require the scope of an unchecked variable to be embedded in the scope of CheckedPtr/CheckRef object that backs it.
3623+
3624+
These are examples of cases that we consider safe:
3625+
3626+
.. code-block:: cpp
3627+
3628+
void foo1() {
3629+
CheckedPtr<RefCountable> counted;
3630+
// The scope of uncounted is EMBEDDED in the scope of counted.
3631+
{
3632+
RefCountable* uncounted = counted.get(); // ok
3633+
}
3634+
}
3635+
3636+
void foo2(CheckedPtr<RefCountable> counted_param) {
3637+
RefCountable* uncounted = counted_param.get(); // ok
3638+
}
3639+
3640+
void FooClass::foo_method() {
3641+
RefCountable* uncounted = this; // ok
3642+
}
3643+
3644+
Here are some examples of situations that we warn about as they *might* be potentially unsafe. The logic is that either we're able to guarantee that a local variable is safe or it's considered unsafe.
35713645
3572-
For the time being we also don't warn about uninitialized uncounted local variables.
3646+
.. code-block:: cpp
3647+
3648+
void foo1() {
3649+
RefCountable* uncounted = new RefCountable; // warn
3650+
}
3651+
3652+
RefCountable* global_uncounted;
3653+
void foo2() {
3654+
RefCountable* uncounted = global_uncounted; // warn
3655+
}
3656+
3657+
void foo3() {
3658+
RefPtr<RefCountable> counted;
3659+
// The scope of uncounted is not EMBEDDED in the scope of counted.
3660+
RefCountable* uncounted = counted.get(); // warn
3661+
}
35733662
35743663
Debug Checkers
35753664
---------------

clang/include/clang/ASTMatchers/ASTMatchers.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -4033,7 +4033,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
40334033
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
40344034
hasType,
40354035
AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl,
4036-
CXXBaseSpecifier),
4036+
CXXBaseSpecifier, ObjCInterfaceDecl),
40374037
internal::Matcher<Decl>, InnerMatcher, 1) {
40384038
QualType QT = internal::getUnderlyingType(Node);
40394039
if (!QT.isNull())
@@ -7433,7 +7433,8 @@ extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
74337433
AST_TYPELOC_TRAVERSE_MATCHER_DECL(
74347434
pointee, getPointee,
74357435
AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
7436-
PointerType, ReferenceType));
7436+
PointerType, ReferenceType,
7437+
ObjCObjectPointerType));
74377438

74387439
/// Matches typedef types.
74397440
///

clang/include/clang/ASTMatchers/ASTMatchersInternal.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ inline QualType getUnderlyingType(const FriendDecl &Node) {
161161
inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) {
162162
return Node.getType();
163163
}
164+
inline QualType getUnderlyingType(const ObjCInterfaceDecl &Node) {
165+
return Node.getTypeForDecl()->getPointeeType();
166+
}
164167

165168
/// Unifies obtaining a `TypeSourceInfo` from different node types.
166169
template <typename T,
@@ -1113,6 +1116,11 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
11131116
return matchesDecl(Node.getDecl(), Finder, Builder);
11141117
}
11151118

1119+
bool matchesSpecialized(const ObjCInterfaceDecl &Node, ASTMatchFinder *Finder,
1120+
BoundNodesTreeBuilder *Builder) const {
1121+
return matchesDecl(Node.getCanonicalDecl(), Finder, Builder);
1122+
}
1123+
11161124
/// Extracts the operator new of the new call and returns whether the
11171125
/// inner matcher matches on it.
11181126
bool matchesSpecialized(const CXXNewExpr &Node,
@@ -1213,7 +1221,7 @@ using HasDeclarationSupportedTypes =
12131221
ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr,
12141222
MemberExpr, QualType, RecordType, TagType,
12151223
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
1216-
UnresolvedUsingType, ObjCIvarRefExpr>;
1224+
UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>;
12171225

12181226
/// A Matcher that allows binding the node it matches to an id.
12191227
///

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

+16
Original file line numberDiff line numberDiff line change
@@ -1787,12 +1787,28 @@ def UncountedLambdaCapturesChecker : Checker<"UncountedLambdaCapturesChecker">,
17871787

17881788
let ParentPackage = WebKitAlpha in {
17891789

1790+
def MemoryUnsafeCastChecker : Checker<"MemoryUnsafeCastChecker">,
1791+
HelpText<"Check for memory unsafe casts from base type to derived type.">,
1792+
Documentation<HasDocumentation>;
1793+
1794+
def NoUncheckedPtrMemberChecker : Checker<"NoUncheckedPtrMemberChecker">,
1795+
HelpText<"Check for no unchecked member variables.">,
1796+
Documentation<HasDocumentation>;
1797+
17901798
def UncountedCallArgsChecker : Checker<"UncountedCallArgsChecker">,
17911799
HelpText<"Check uncounted call arguments.">,
17921800
Documentation<HasDocumentation>;
17931801

1802+
def UncheckedCallArgsChecker : Checker<"UncheckedCallArgsChecker">,
1803+
HelpText<"Check unchecked call arguments.">,
1804+
Documentation<HasDocumentation>;
1805+
17941806
def UncountedLocalVarsChecker : Checker<"UncountedLocalVarsChecker">,
17951807
HelpText<"Check uncounted local variables.">,
17961808
Documentation<HasDocumentation>;
17971809

1810+
def UncheckedLocalVarsChecker : Checker<"UncheckedLocalVarsChecker">,
1811+
HelpText<"Check unchecked local variables.">,
1812+
Documentation<HasDocumentation>;
1813+
17981814
} // end alpha.webkit

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,8 @@ AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType,
10861086
AST_TYPELOC_TRAVERSE_MATCHER_DEF(
10871087
pointee,
10881088
AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType,
1089-
PointerType, ReferenceType));
1089+
PointerType, ReferenceType,
1090+
ObjCObjectPointerType));
10901091

10911092
const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
10921093
ompExecutableDirective;

clang/lib/Rewrite/HTMLRewrite.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ h1 { font-size:14pt }
334334
.keyword { color: blue }
335335
.string_literal { color: red }
336336
.directive { color: darkmagenta }
337+
.anchor { display: block; height: 250px; margin-top: -250px; visibility: hidden; }
337338
338339
/* Macros and variables could have pop-up notes hidden by default.
339340
- Macro pop-up: expansion of the macro

clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,14 @@ add_clang_library(clangStaticAnalyzerCheckers
133133
VLASizeChecker.cpp
134134
ValistChecker.cpp
135135
VirtualCallChecker.cpp
136-
WebKit/NoUncountedMembersChecker.cpp
136+
WebKit/RawPtrRefMemberChecker.cpp
137137
WebKit/ASTUtils.cpp
138+
WebKit/MemoryUnsafeCastChecker.cpp
138139
WebKit/PtrTypesSemantics.cpp
139140
WebKit/RefCntblBaseVirtualDtorChecker.cpp
140-
WebKit/UncountedCallArgsChecker.cpp
141+
WebKit/RawPtrRefCallArgsChecker.cpp
141142
WebKit/UncountedLambdaCapturesChecker.cpp
142-
WebKit/UncountedLocalVarsChecker.cpp
143+
WebKit/RawPtrRefLocalVarsChecker.cpp
143144

144145
LINK_LIBS
145146
clangAST

0 commit comments

Comments
 (0)