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;
113 return Builder->removeBindings([
this](
const BoundNodesMap &Nodes) {
115 const auto *Derived = Nodes.getNodeAs<
CXXRecordDecl>(this->DerivedID);
118 if (!CTSD || !Derived)
124 if (!ArgType.isNull() && ArgType->getAsCXXRecordDecl() == Derived)
138 return ignoringParenImpCasts(
anyOf(
141 hasUnaryOperand(ignoringParenImpCasts(
cxxThisExpr())))));
144void MemoryUnsafeCastChecker::checkASTCodeBody(
const Decl *D,
151 auto MatchExprPtr =
allOf(
157 isCRTPCast(BaseNode, DerivedNode)))));
158 auto MatchExprPtrObjC =
allOf(
163 .bind(DerivedNode)))))));
164 auto MatchExprRefTypeDef =
165 allOf(hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
recordType(
169 .bind(DerivedNode)))))),
172 isCRTPCast(BaseNode, DerivedNode)))));
173 auto MatchExprPtrVoidCast =
allOf(
176 hasSourceExpression(ignoringImpCasts(
183 .bind(DerivedNode)));
187 MatchExprPtrObjC, MatchExprPtrVoidCast))
188 .bind(WarnRecordDecl);
193 for (BoundNodes
Match : Matches)
199 hasSourceExpression(ignoringImpCasts(
201 .bind(WarnRecordDecl);
202 auto MatchCallPtrVoidArgCast =
callExpr(
203 hasAnyArgument(
anyOf(VoidPtrCast,
206 .bind(DerivedNode)));
207 auto CallArgCast =
stmt(MatchCallPtrVoidArgCast);
210 for (BoundNodes
Match : MatchesCallArgCast)
214 auto MatchExprPtrUnrelatedTypes =
allOf(
219 isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))),
221 isSameOrDerivedFrom(equalsBoundNode(ToCastNode))))))));
222 auto MatchExprPtrObjCUnrelatedTypes =
allOf(
228 ignoringImpCasts(hasType(
230 isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))))))),
231 hasSourceExpression(ignoringImpCasts(hasType(
233 isSameOrDerivedFrom(equalsBoundNode(ToCastNode))))))))))));
234 auto MatchExprRefTypeDefUnrelated =
allOf(
235 hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
recordType(
237 hasType(hasUnqualifiedDesugaredType(
240 hasType(hasUnqualifiedDesugaredType(
242 isSameOrDerivedFrom(equalsBoundNode(FromCastNode)))))))),
243 hasSourceExpression(hasType(hasUnqualifiedDesugaredType(
245 isSameOrDerivedFrom(equalsBoundNode(ToCastNode))))))))))));
247 auto ExplicitCastUnrelated =
249 MatchExprPtrObjCUnrelatedTypes,
250 MatchExprRefTypeDefUnrelated))
251 .bind(WarnRecordDecl);
252 auto CastUnrelated =
stmt(ExplicitCastUnrelated);
255 for (BoundNodes
Match : MatchesUnrelatedTypes)
263 auto CastArgFromIdToSpecificType =
265 hasCastKind(CK_BitCast),
267 ignoringParenImpCasts(hasType(
qualType(isObjCIdType())))),
270 .bind(WarnRecordDecl);
271 auto MatchCallArgFromId =
275 auto MatchesCallArgFromId =
278 for (BoundNodes
Match : MatchesCallArgFromId)
282void ento::registerMemoryUnsafeCastChecker(CheckerManager &Mgr) {
286bool 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) { ....
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.
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...
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.
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',...