25static constexpr const char *
const BaseNode =
"BaseNode";
26static constexpr const char *
const DerivedNode =
"DerivedNode";
27static constexpr const char *
const FromCastNode =
"FromCast";
28static constexpr const char *
const ToCastNode =
"ToCast";
29static constexpr const char *
const WarnRecordDecl =
"WarnRecordDecl";
31class MemoryUnsafeCastChecker :
public Checker<check::ASTCodeBody> {
32 BugType BT{
this,
"Unsafe cast",
"WebKit coding guidelines"};
35 void checkASTCodeBody(
const Decl *D, AnalysisManager &Mgr,
36 BugReporter &BR)
const;
42 const MemoryUnsafeCastChecker *
Checker,
47 assert(CE &&
Base && Derived);
49 std::string Diagnostics;
50 llvm::raw_string_ostream
OS(Diagnostics);
51 OS <<
"Unsafe cast from base type '" <<
Base->getNameAsString()
52 <<
"' to derived type '" << Derived->getNameAsString() <<
"'";
55 auto Report = std::make_unique<BasicBugReport>(BT,
OS.str(), BSLoc);
56 Report->addRange(CE->getSourceRange());
63 const MemoryUnsafeCastChecker *
Checker,
68 assert(CE && FromCast && ToCast);
70 std::string Diagnostics;
71 llvm::raw_string_ostream
OS(Diagnostics);
72 OS <<
"Unsafe cast from type '" << FromCast->getNameAsString()
73 <<
"' to an unrelated type '" << ToCast->getNameAsString() <<
"'";
76 auto Report = std::make_unique<BasicBugReport>(BT,
OS.str(), BSLoc);
77 Report->addRange(CE->getSourceRange());
84 const MemoryUnsafeCastChecker *
Checker,
88 assert(CE && Derived);
90 std::string Diagnostics;
91 llvm::raw_string_ostream
OS(Diagnostics);
92 OS <<
"Unsafe implicit cast from 'id' to specific type '"
93 << Derived->getNameAsString() <<
"'";
96 auto Report = std::make_unique<BasicBugReport>(BT,
OS.str(), BSLoc);
97 Report->addRange(CE->getSourceRange());
103using BoundNodesMap = ::clang::ast_matchers::internal::BoundNodesMap;
112 return Builder->removeBindings([&](
const BoundNodesMap &Nodes) {
113 const auto *Bound = Nodes.getNodeAs<
Decl>(ID);
123 return Builder->removeBindings([
this](
const BoundNodesMap &Nodes) {
125 const auto *Derived = Nodes.getNodeAs<
CXXRecordDecl>(this->DerivedID);
128 if (!CTSD || !Derived)
134 if (ArgType.isNull())
151 return ignoringParenImpCasts(
anyOf(
154 hasUnaryOperand(ignoringParenImpCasts(
cxxThisExpr())))));
157void MemoryUnsafeCastChecker::checkASTCodeBody(
const Decl *D,
164 auto MatchExprPtr =
allOf(
168 isDerivedFrom(hasSameCanonicalDeclAsBoundNode(BaseNode)))
172 isCRTPCast(BaseNode, DerivedNode)))));
173 auto MatchExprPtrObjC =
allOf(
178 isDerivedFrom(hasSameCanonicalDeclAsBoundNode(BaseNode)))
179 .bind(DerivedNode)))))));
180 auto MatchExprRefTypeDef =
allOf(
181 hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
185 isDerivedFrom(hasSameCanonicalDeclAsBoundNode(BaseNode)))
186 .bind(DerivedNode)))))),
189 isCRTPCast(BaseNode, DerivedNode)))));
190 auto MatchExprPtrVoidCast =
193 hasSourceExpression(ignoringImpCasts(
201 isDerivedFrom(hasSameCanonicalDeclAsBoundNode(BaseNode)))
202 .bind(DerivedNode)));
206 MatchExprPtrObjC, MatchExprPtrVoidCast))
207 .bind(WarnRecordDecl);
212 for (BoundNodes
Match : Matches)
218 hasSourceExpression(ignoringImpCasts(
220 .bind(WarnRecordDecl);
221 auto MatchCallPtrVoidArgCast =
callExpr(
222 hasAnyArgument(
anyOf(VoidPtrCast,
226 isDerivedFrom(hasSameCanonicalDeclAsBoundNode(BaseNode)))
227 .bind(DerivedNode)));
228 auto CallArgCast =
stmt(MatchCallPtrVoidArgCast);
231 for (BoundNodes
Match : MatchesCallArgCast)
235 auto MatchExprPtrUnrelatedTypes =
allOf(
240 hasSameCanonicalDeclAsBoundNode(FromCastNode)))),
243 hasSameCanonicalDeclAsBoundNode(ToCastNode))))))));
244 auto MatchExprPtrObjCUnrelatedTypes =
allOf(
252 hasSameCanonicalDeclAsBoundNode(FromCastNode)))))))),
255 hasSameCanonicalDeclAsBoundNode(ToCastNode))))))))))));
256 auto MatchExprRefTypeDefUnrelated =
allOf(
257 hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
recordType(
259 hasType(hasUnqualifiedDesugaredType(
262 hasType(hasUnqualifiedDesugaredType(
264 hasSameCanonicalDeclAsBoundNode(FromCastNode)))))))),
265 hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
267 hasSameCanonicalDeclAsBoundNode(ToCastNode))))))))))));
269 auto ExplicitCastUnrelated =
271 MatchExprPtrObjCUnrelatedTypes,
272 MatchExprRefTypeDefUnrelated))
273 .bind(WarnRecordDecl);
274 auto CastUnrelated =
stmt(ExplicitCastUnrelated);
277 for (BoundNodes
Match : MatchesUnrelatedTypes)
285 auto CastArgFromIdToSpecificType =
287 hasCastKind(CK_BitCast),
289 ignoringParenImpCasts(hasType(
qualType(isObjCIdType())))),
292 .bind(WarnRecordDecl);
293 auto MatchCallArgFromId =
297 auto MatchesCallArgFromId =
300 for (BoundNodes
Match : MatchesCallArgFromId)
304void ento::registerMemoryUnsafeCastChecker(CheckerManager &Mgr) {
308bool ento::shouldRegisterMemoryUnsafeCastChecker(
const CheckerManager &mgr) {
#define AST_MATCHER(Type, DefineMatcher)
AST_MATCHER(Type, DefineMatcher) { ... } defines a zero parameter function named DefineMatcher() that...
#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2)
AST_MATCHER_P2( Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ....
#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)
AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } defines a single-parameter function name...
static void emitDiagnostics(const BoundNodes &Nodes, BugReporter &BR, AnalysisDeclContext *ADC, const MemoryUnsafeCastChecker *Checker, const BugType &BT)
static decltype(auto) hasTypePointingTo(DeclarationMatcher DeclM)
static void emitDiagnosticsIdArg(const BoundNodes &Nodes, BugReporter &BR, AnalysisDeclContext *ADC, const MemoryUnsafeCastChecker *Checker, const BugType &BT)
static decltype(auto) isThisOrDerefThis()
static void emitDiagnosticsUnrelated(const BoundNodes &Nodes, BugReporter &BR, AnalysisDeclContext *ADC, const MemoryUnsafeCastChecker *Checker, const BugType &BT)
static decltype(auto) hasTypePointingTo(DeclarationMatcher DeclM)
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
Represents a C++ struct/union/class.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Decl - This represents one declaration (or definition), e.g.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
This represents one expression.
This represents a decl that may have a name.
A (possibly-)qualified type.
Represents a template argument.
@ Type
The template argument is a type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Maps string IDs to AST nodes matched by parts of a matcher.
const T * getNodeAs(StringRef ID) const
Returns the AST node bound to ID.
ASTContext & getASTContext() override
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
const internal::VariadicOperatorMatcherFunc< 1, 1 > unless
Matches if the provided matcher does not match.
const AstTypeMatcher< ObjCObjectPointerType > objcObjectPointerType
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
const internal::VariadicDynCastAllOfMatcher< Stmt, ImplicitCastExpr > implicitCastExpr
Matches the implicit cast nodes of Clang's AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::ArgumentAdaptingMatcherFunc< internal::ForEachDescendantMatcher > forEachDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator > unaryOperator
Matches unary operator expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ObjCMessageExpr > objcMessageExpr
Matches ObjectiveC Message invocation expressions.
const internal::VariadicDynCastAllOfMatcher< Decl, TemplateTypeParmDecl > templateTypeParmDecl
Matches template type parameter declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, ExplicitCastExpr > explicitCastExpr
Matches explicit cast expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXConstructExpr > cxxConstructExpr
Matches constructor call expressions (including implicit ones).
const internal::VariadicDynCastAllOfMatcher< Decl, ObjCInterfaceDecl > objcInterfaceDecl
Matches Objective-C interface declarations.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> allOf
Matches if all given matchers match.
const AstTypeMatcher< RecordType > recordType
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
internal::PolymorphicMatcher< internal::HasDeclarationMatcher, void(internal::HasDeclarationSupportedTypes), internal::Matcher< Decl > > hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXThisExpr > cxxThisExpr
Matches implicit and explicit this expressions.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Cast(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...