blob: 0a274292aa39f7f2e88e511a6e10d8529d0d8a95 [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"
Benjamin Kramercfeacf52016-05-27 14:27:13 +000020#include <utility>
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000021
22using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000023using namespace ento;
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000024
25namespace {
26
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000027class UndefBranchChecker : public Checker<check::BranchCondition> {
Ahmed Charlesb8984322014-03-07 20:03:18 +000028 mutable std::unique_ptr<BuiltinBug> BT;
Zhongxing Xu5f766202009-11-23 03:29:59 +000029
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000030 struct FindUndefExpr {
Ted Kremenek49b1e382012-01-26 21:29:00 +000031 ProgramStateRef St;
Ted Kremenek632e3b72012-01-06 22:09:28 +000032 const LocationContext *LCtx;
Zhongxing Xu5f766202009-11-23 03:29:59 +000033
Ted Kremenek3a0678e2015-09-08 03:50:52 +000034 FindUndefExpr(ProgramStateRef S, const LocationContext *L)
Benjamin Kramercfeacf52016-05-27 14:27:13 +000035 : St(std::move(S)), LCtx(L) {}
Zhongxing Xu5f766202009-11-23 03:29:59 +000036
Ted Kremenek5ef32db2011-08-12 23:37:29 +000037 const Expr *FindExpr(const Expr *Ex) {
Zhongxing Xu5f766202009-11-23 03:29:59 +000038 if (!MatchesCriteria(Ex))
Craig Topper0dbb7832014-05-27 02:45:47 +000039 return nullptr;
Zhongxing Xu5f766202009-11-23 03:29:59 +000040
Benjamin Kramer973431b2015-07-03 15:12:24 +000041 for (const Stmt *SubStmt : Ex->children())
42 if (const Expr *ExI = dyn_cast_or_null<Expr>(SubStmt))
43 if (const Expr *E2 = FindExpr(ExI))
44 return E2;
Zhongxing Xu5f766202009-11-23 03:29:59 +000045
46 return Ex;
47 }
48
Ted Kremenek3a0678e2015-09-08 03:50:52 +000049 bool MatchesCriteria(const Expr *Ex) {
Ted Kremenek632e3b72012-01-06 22:09:28 +000050 return St->getSVal(Ex, LCtx).isUndef();
51 }
Zhongxing Xu5f766202009-11-23 03:29:59 +000052 };
53
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000054public:
Anna Zaksf3805342011-10-25 19:56:54 +000055 void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const;
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000056};
57
Alexander Kornienkoab9db512015-06-22 23:07:51 +000058}
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000059
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +000060void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
Anna Zaksf3805342011-10-25 19:56:54 +000061 CheckerContext &Ctx) const {
Ted Kremenek632e3b72012-01-06 22:09:28 +000062 SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000063 if (X.isUndef()) {
Anna Zaks6d285c52011-10-18 23:06:21 +000064 // Generate a sink node, which implicitly marks both outgoing branches as
65 // infeasible.
Devin Coughline39bd402015-09-16 22:03:05 +000066 ExplodedNode *N = Ctx.generateErrorNode();
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000067 if (N) {
Zhongxing Xu56dd5f02009-11-23 03:20:54 +000068 if (!BT)
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000069 BT.reset(new BuiltinBug(
70 this, "Branch condition evaluates to a garbage value"));
Zhongxing Xu5f766202009-11-23 03:29:59 +000071
72 // What's going on here: we want to highlight the subexpression of the
73 // condition that is the most likely source of the "uninitialized
74 // branch condition." We do a recursive walk of the condition's
75 // subexpressions and roughly look for the most nested subexpression
76 // that binds to Undefined. We then highlight that expression's range.
Zhongxing Xu5f766202009-11-23 03:29:59 +000077
78 // Get the predecessor node and check if is a PostStmt with the Stmt
79 // being the terminator condition. We want to inspect the state
80 // of that node instead because it will contain main information about
81 // the subexpressions.
Zhongxing Xu5f766202009-11-23 03:29:59 +000082
83 // Note: any predecessor will do. They should have identical state,
84 // since all the BlockEdge did was act as an error sink since the value
85 // had to already be undefined.
Anna Zaksc42197d2011-10-03 21:16:32 +000086 assert (!N->pred_empty());
87 const Expr *Ex = cast<Expr>(Condition);
Zhongxing Xu5f766202009-11-23 03:29:59 +000088 ExplodedNode *PrevN = *N->pred_begin();
89 ProgramPoint P = PrevN->getLocation();
Ted Kremenek49b1e382012-01-26 21:29:00 +000090 ProgramStateRef St = N->getState();
Zhongxing Xu5f766202009-11-23 03:29:59 +000091
David Blaikie87396b92013-02-21 22:23:56 +000092 if (Optional<PostStmt> PS = P.getAs<PostStmt>())
Zhongxing Xu5f766202009-11-23 03:29:59 +000093 if (PS->getStmt() == Ex)
94 St = PrevN->getState();
95
Ted Kremenek632e3b72012-01-06 22:09:28 +000096 FindUndefExpr FindIt(St, Ctx.getLocationContext());
Zhongxing Xu5f766202009-11-23 03:29:59 +000097 Ex = FindIt.FindExpr(Ex);
Ted Kremenek02d6aca2009-11-23 18:12:03 +000098
99 // Emit the bug report.
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000100 auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
Jordan Rosea0f7d352012-08-28 00:50:51 +0000101 bugreporter::trackNullOrUndefValue(N, Ex, *R);
Zhongxing Xu5f766202009-11-23 03:29:59 +0000102 R->addRange(Ex->getSourceRange());
103
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000104 Ctx.emitReport(std::move(R));
Zhongxing Xu56dd5f02009-11-23 03:20:54 +0000105 }
Zhongxing Xu56dd5f02009-11-23 03:20:54 +0000106 }
107}
Argyrios Kyrtzidis753b3ca2011-02-28 01:27:33 +0000108
109void ento::registerUndefBranchChecker(CheckerManager &mgr) {
110 mgr.registerChecker<UndefBranchChecker>();
111}