| 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 | |