1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" |
15 | #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" |
16 | #include "clang/StaticAnalyzer/Core/Checker.h" |
17 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
18 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" |
19 | #include <utility> |
20 | |
21 | using namespace clang; |
22 | using namespace ento; |
23 | |
24 | namespace { |
25 | |
26 | class UndefBranchChecker : public Checker<check::BranchCondition> { |
27 | mutable std::unique_ptr<BuiltinBug> BT; |
28 | |
29 | struct FindUndefExpr { |
30 | ProgramStateRef St; |
31 | const LocationContext *LCtx; |
32 | |
33 | FindUndefExpr(ProgramStateRef S, const LocationContext *L) |
34 | : St(std::move(S)), LCtx(L) {} |
35 | |
36 | const Expr *FindExpr(const Expr *Ex) { |
37 | if (!MatchesCriteria(Ex)) |
38 | return nullptr; |
39 | |
40 | for (const Stmt *SubStmt : Ex->children()) |
41 | if (const Expr *ExI = dyn_cast_or_null<Expr>(SubStmt)) |
42 | if (const Expr *E2 = FindExpr(ExI)) |
43 | return E2; |
44 | |
45 | return Ex; |
46 | } |
47 | |
48 | bool MatchesCriteria(const Expr *Ex) { |
49 | return St->getSVal(Ex, LCtx).isUndef(); |
50 | } |
51 | }; |
52 | |
53 | public: |
54 | void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const; |
55 | }; |
56 | |
57 | } |
58 | |
59 | void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, |
60 | CheckerContext &Ctx) const { |
61 | SVal X = Ctx.getSVal(Condition); |
62 | if (X.isUndef()) { |
63 | |
64 | |
65 | ExplodedNode *N = Ctx.generateErrorNode(); |
66 | if (N) { |
67 | if (!BT) |
68 | BT.reset(new BuiltinBug( |
69 | this, "Branch condition evaluates to a garbage value")); |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | pred_empty()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp", 85, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (!N->pred_empty()); |
86 | const Expr *Ex = cast<Expr>(Condition); |
87 | ExplodedNode *PrevN = *N->pred_begin(); |
88 | ProgramPoint P = PrevN->getLocation(); |
89 | ProgramStateRef St = N->getState(); |
90 | |
91 | if (Optional<PostStmt> PS = P.getAs<PostStmt>()) |
92 | if (PS->getStmt() == Ex) |
93 | St = PrevN->getState(); |
94 | |
95 | FindUndefExpr FindIt(St, Ctx.getLocationContext()); |
96 | Ex = FindIt.FindExpr(Ex); |
97 | |
98 | |
99 | auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N); |
100 | bugreporter::trackExpressionValue(N, Ex, *R); |
101 | R->addRange(Ex->getSourceRange()); |
102 | |
103 | Ctx.emitReport(std::move(R)); |
104 | } |
105 | } |
106 | } |
107 | |
108 | void ento::registerUndefBranchChecker(CheckerManager &mgr) { |
109 | mgr.registerChecker<UndefBranchChecker>(); |
110 | } |
111 | |
112 | bool ento::shouldRegisterUndefBranchChecker(const LangOptions &LO) { |
113 | return true; |
114 | } |
115 | |