blob: ed17610e411697da7065e5497f73610e8110c82c [file] [log] [blame]
Zhongxing Xu56dd5f02009-11-23 03:20:54 +00001//=== UndefBranchChecker.cpp -----------------------------------*- C++ -*--===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines UndefBranchChecker, which checks for undefined branch
11// condition.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +000015#include "ClangSACheckers.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000017#include "clang/StaticAnalyzer/Core/Checker.h"
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +000018#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000020
21using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000022using namespace ento;
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000023
24namespace {
25
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000026class UndefBranchChecker : public Checker<check::BranchCondition> {
Ahmed Charlesb8984322014-03-07 20:03:18 +000027 mutable std::unique_ptr<BuiltinBug> BT;
Zhongxing Xu5f766202009-11-23 03:29:59 +000028
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000029 struct FindUndefExpr {
Ted Kremenek49b1e382012-01-26 21:29:00 +000030 ProgramStateRef St;
Ted Kremenek632e3b72012-01-06 22:09:28 +000031 const LocationContext *LCtx;
Zhongxing Xu5f766202009-11-23 03:29:59 +000032
Ted Kremenek3a0678e2015-09-08 03:50:52 +000033 FindUndefExpr(ProgramStateRef S, const LocationContext *L)
Ted Kremenek632e3b72012-01-06 22:09:28 +000034 : St(S), LCtx(L) {}
Zhongxing Xu5f766202009-11-23 03:29:59 +000035
Ted Kremenek5ef32db2011-08-12 23:37:29 +000036 const Expr *FindExpr(const Expr *Ex) {
Zhongxing Xu5f766202009-11-23 03:29:59 +000037 if (!MatchesCriteria(Ex))
Craig Topper0dbb7832014-05-27 02:45:47 +000038 return nullptr;
Zhongxing Xu5f766202009-11-23 03:29:59 +000039
Benjamin Kramer973431b2015-07-03 15:12:24 +000040 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;
Zhongxing Xu5f766202009-11-23 03:29:59 +000044
45 return Ex;
46 }
47
Ted Kremenek3a0678e2015-09-08 03:50:52 +000048 bool MatchesCriteria(const Expr *Ex) {
Ted Kremenek632e3b72012-01-06 22:09:28 +000049 return St->getSVal(Ex, LCtx).isUndef();
50 }
Zhongxing Xu5f766202009-11-23 03:29:59 +000051 };
52
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000053public:
Anna Zaksf3805342011-10-25 19:56:54 +000054 void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const;
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000055};
56
Alexander Kornienkoab9db512015-06-22 23:07:51 +000057}
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000058
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +000059void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
Anna Zaksf3805342011-10-25 19:56:54 +000060 CheckerContext &Ctx) const {
Ted Kremenek632e3b72012-01-06 22:09:28 +000061 SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000062 if (X.isUndef()) {
Anna Zaks6d285c52011-10-18 23:06:21 +000063 // Generate a sink node, which implicitly marks both outgoing branches as
64 // infeasible.
Devin Coughline39bd402015-09-16 22:03:05 +000065 ExplodedNode *N = Ctx.generateErrorNode();
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000066 if (N) {
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000067 if (!BT)
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000068 BT.reset(new BuiltinBug(
69 this, "Branch condition evaluates to a garbage value"));
Zhongxing Xu5f766202009-11-23 03:29:59 +000070
71 // What's going on here: we want to highlight the subexpression of the
72 // condition that is the most likely source of the "uninitialized
73 // branch condition." We do a recursive walk of the condition's
74 // subexpressions and roughly look for the most nested subexpression
75 // that binds to Undefined. We then highlight that expression's range.
Zhongxing Xu5f766202009-11-23 03:29:59 +000076
77 // Get the predecessor node and check if is a PostStmt with the Stmt
78 // being the terminator condition. We want to inspect the state
79 // of that node instead because it will contain main information about
80 // the subexpressions.
Zhongxing Xu5f766202009-11-23 03:29:59 +000081
82 // Note: any predecessor will do. They should have identical state,
83 // since all the BlockEdge did was act as an error sink since the value
84 // had to already be undefined.
Anna Zaksc42197d2011-10-03 21:16:32 +000085 assert (!N->pred_empty());
86 const Expr *Ex = cast<Expr>(Condition);
Zhongxing Xu5f766202009-11-23 03:29:59 +000087 ExplodedNode *PrevN = *N->pred_begin();
88 ProgramPoint P = PrevN->getLocation();
Ted Kremenek49b1e382012-01-26 21:29:00 +000089 ProgramStateRef St = N->getState();
Zhongxing Xu5f766202009-11-23 03:29:59 +000090
David Blaikie87396b92013-02-21 22:23:56 +000091 if (Optional<PostStmt> PS = P.getAs<PostStmt>())
Zhongxing Xu5f766202009-11-23 03:29:59 +000092 if (PS->getStmt() == Ex)
93 St = PrevN->getState();
94
Ted Kremenek632e3b72012-01-06 22:09:28 +000095 FindUndefExpr FindIt(St, Ctx.getLocationContext());
Zhongxing Xu5f766202009-11-23 03:29:59 +000096 Ex = FindIt.FindExpr(Ex);
Ted Kremenek02d6aca2009-11-23 18:12:03 +000097
98 // Emit the bug report.
Aaron Ballman8d3a7a52015-06-23 13:15:32 +000099 auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
Jordan Rosea0f7d352012-08-28 00:50:51 +0000100 bugreporter::trackNullOrUndefValue(N, Ex, *R);
Zhongxing Xu5f766202009-11-23 03:29:59 +0000101 R->addRange(Ex->getSourceRange());
102
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000103 Ctx.emitReport(std::move(R));
Zhongxing Xu56dd5f02009-11-23 03:20:54 +0000104 }
Zhongxing Xu56dd5f02009-11-23 03:20:54 +0000105 }
106}
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +0000107
108void ento::registerUndefBranchChecker(CheckerManager &mgr) {
109 mgr.registerChecker<UndefBranchChecker>();
110}