clang 10.0.0git

OSObjectCStyleCast.cpp
Go to the documentation of this file.
1 //===- OSObjectCStyleCast.cpp ------------------------------------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines OSObjectCStyleCast checker, which checks for C-style casts
10 // of OSObjects. Such casts almost always indicate a code smell,
11 // as an explicit static or dynamic cast should be used instead.
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15 #include "clang/ASTMatchers/ASTMatchFinder.h"
16 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
17 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18 #include "clang/StaticAnalyzer/Core/Checker.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20 #include "llvm/Support/Debug.h"
21
22 using namespace clang;
23 using namespace ento;
24 using namespace ast_matchers;
25
26 namespace {
27
28 const char *WarnAtNode = "OSObjCast";
29
30 class OSObjectCStyleCastChecker : public Checker<check::ASTCodeBody> {
31 public:
32 void checkASTCodeBody(const Decl *D,
33 AnalysisManager &AM,
34 BugReporter &BR) const;
35 };
36
37 static void emitDiagnostics(const BoundNodes &Nodes,
38 BugReporter &BR,
39 AnalysisDeclContext *ADC,
40 const OSObjectCStyleCastChecker *Checker) {
41 const auto *CE = Nodes.getNodeAs<CastExpr>(WarnAtNode);
42 assert(CE);
43
44 std::string Diagnostics;
45 llvm::raw_string_ostream OS(Diagnostics);
46 OS << "C-style cast of OSObject. Use OSDynamicCast instead.";
47
48 BR.EmitBasicReport(
49 ADC->getDecl(),
50 Checker,
51 /*Name=*/"OSObject C-Style Cast",
52 /*BugCategory=*/"Security",
53 OS.str(),
54 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), ADC),
55 CE->getSourceRange());
56 }
57
58 static auto hasTypePointingTo(DeclarationMatcher DeclM)
59 -> decltype(hasType(pointerType())) {
60 return hasType(pointerType(pointee(hasDeclaration(DeclM))));
61 }
62
63 void OSObjectCStyleCastChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM,
64 BugReporter &BR) const {
65
66 AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
67
68 auto DynamicCastM = callExpr(callee(functionDecl(hasName("safeMetaCast"))));
69
70 auto OSObjTypeM = hasTypePointingTo(cxxRecordDecl(isDerivedFrom("OSMetaClassBase")));
71 auto OSObjSubclassM = hasTypePointingTo(
72 cxxRecordDecl(isDerivedFrom("OSObject")));
73
74 auto CastM = cStyleCastExpr(
75 allOf(hasSourceExpression(allOf(OSObjTypeM, unless(DynamicCastM))),
76 OSObjSubclassM)).bind(WarnAtNode);
77
78 auto Matches = match(stmt(forEachDescendant(CastM)), *D->getBody(), AM.getASTContext());
79 for (BoundNodes Match : Matches)
80 emitDiagnostics(Match, BR, ADC, this);
81 }
82 }
83
84 void ento::registerOSObjectCStyleCast(CheckerManager &Mgr) {
85 Mgr.registerChecker<OSObjectCStyleCastChecker>();
86 }
87
88 bool ento::shouldRegisterOSObjectCStyleCast(const LangOptions &LO) {
89 return true;
90 }
ento
clang::ast_matchers::callExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
Definition: ASTMatchersInternal.cpp:668
clang::ast_matchers::stmt
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Definition: ASTMatchersInternal.cpp:661
clang::Decl::getBody
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:986
ASTMatchFinder.h
clang::ast_matchers::hasDeclaration
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:3084
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
BugType.h
clang::ast_matchers::pointerType
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
Definition: ASTMatchersInternal.cpp:872
clang::ast_matchers::allOf
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> allOf
Matches if all given matchers match.
Definition: ASTMatchersInternal.cpp:823
clang::ast_matchers::functionDecl
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
Definition: ASTMatchersInternal.cpp:657
Nodes
BoundNodesTreeBuilder Nodes
Definition: ASTMatchFinder.cpp:74
clang::AnalysisDeclContext
AnalysisDeclContext contains the context data for the function or method under analysis.
Definition: AnalysisDeclContext.h:69
Checker.h
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:53
clang::ast_matchers::BoundNodes::getNodeAs
const T * getNodeAs(StringRef ID) const
Returns the AST node bound to ID.
Definition: ASTMatchers.h:111
clang::CastExpr
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3150
clang::ast_matchers::match
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
Definition: ASTMatchFinder.h:298
clang::ast_matchers::forEachDescendant
const internal::ArgumentAdaptingMatcherFunc< internal::ForEachDescendantMatcher > forEachDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
Definition: ASTMatchersInternal.cpp:839
BugReporter.h
AnalysisManager.h
clang::ast_matchers::cStyleCastExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, CStyleCastExpr > cStyleCastExpr
Matches a C-style cast expression.
Definition: ASTMatchersInternal.cpp:801
BuiltinCheckerRegistration.h
clang::ast_matchers::BoundNodes
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:104
clang::ento::PathDiagnosticLocation::createBegin
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Definition: PathDiagnostic.cpp:564
clang::AnalysisDeclContext::getDecl
const Decl * getDecl() const
Definition: AnalysisDeclContext.h:104
emitDiagnostics
static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, AnalysisManager &AM, const ObjCAutoreleaseWriteChecker *Checker)
Definition: ObjCAutoreleaseWriteChecker.cpp:108
clang::ast_matchers::unless
const internal::VariadicOperatorMatcherFunc< 1, 1 > unless
Matches if the provided matcher does not match.
Definition: ASTMatchersInternal.cpp:850
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:21
ast_matchers
clang::ast_matchers::cxxRecordDecl
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
Definition: ASTMatchersInternal.cpp:616
clang::ento::ObjKind::OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
clang::ast_matchers::hasName
internal::Matcher< NamedDecl > hasName(const std::string &Name)
Matches NamedDecl nodes that have the specified name.
Definition: ASTMatchers.h:2649
clang::ast_matchers::DeclarationMatcher
internal::Matcher< Decl > DeclarationMatcher
Types of matchers for the top-level classes in the AST class hierarchy.
Definition: ASTMatchers.h:138