blob: 90883456b17c2d2652ab0fcc063c3232aea708d8 [file] [log] [blame]
Zhongxing Xu0835e4c2009-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
15#include "GRExprEngineInternalChecks.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000016#include "clang/Checker/BugReporter/BugType.h"
Ted Kremenek1309f9a2010-01-25 04:41:41 +000017#include "clang/Checker/PathSensitive/Checker.h"
Zhongxing Xu0835e4c2009-11-23 03:20:54 +000018
19using namespace clang;
20
21namespace {
22
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000023class UndefBranchChecker : public Checker {
Zhongxing Xu0835e4c2009-11-23 03:20:54 +000024 BuiltinBug *BT;
Zhongxing Xuf155dbf2009-11-23 03:29:59 +000025
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000026 struct FindUndefExpr {
Zhongxing Xuf155dbf2009-11-23 03:29:59 +000027 GRStateManager& VM;
28 const GRState* St;
29
30 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
31
32 Expr* FindExpr(Expr* Ex) {
33 if (!MatchesCriteria(Ex))
34 return 0;
35
36 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
37 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
38 Expr* E2 = FindExpr(ExI);
39 if (E2) return E2;
40 }
41
42 return Ex;
43 }
44
Ted Kremenek13976632010-02-08 16:18:51 +000045 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Zhongxing Xuf155dbf2009-11-23 03:29:59 +000046 };
47
Zhongxing Xu0835e4c2009-11-23 03:20:54 +000048public:
49 UndefBranchChecker() : BT(0) {}
50 static void *getTag();
51 void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng,
52 Stmt *Condition, void *tag);
53};
54
55}
56
57void clang::RegisterUndefBranchChecker(GRExprEngine &Eng) {
58 Eng.registerCheck(new UndefBranchChecker());
59}
60
61void *UndefBranchChecker::getTag() {
62 static int x;
63 return &x;
64}
65
66void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder,
67 GRExprEngine &Eng,
68 Stmt *Condition, void *tag) {
69 const GRState *state = Builder.getState();
Ted Kremenek13976632010-02-08 16:18:51 +000070 SVal X = state->getSVal(Condition);
Zhongxing Xu0835e4c2009-11-23 03:20:54 +000071 if (X.isUndef()) {
72 ExplodedNode *N = Builder.generateNode(state, true);
73 if (N) {
74 N->markAsSink();
75 if (!BT)
Ted Kremenek998c1332009-11-23 17:58:48 +000076 BT = new BuiltinBug("Branch condition evaluates to a garbage value");
Zhongxing Xuf155dbf2009-11-23 03:29:59 +000077
78 // What's going on here: we want to highlight the subexpression of the
79 // condition that is the most likely source of the "uninitialized
80 // branch condition." We do a recursive walk of the condition's
81 // subexpressions and roughly look for the most nested subexpression
82 // that binds to Undefined. We then highlight that expression's range.
83 BlockEdge B = cast<BlockEdge>(N->getLocation());
84 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
85 assert (Ex && "Block must have a terminator.");
86
87 // Get the predecessor node and check if is a PostStmt with the Stmt
88 // being the terminator condition. We want to inspect the state
89 // of that node instead because it will contain main information about
90 // the subexpressions.
91 assert (!N->pred_empty());
92
93 // Note: any predecessor will do. They should have identical state,
94 // since all the BlockEdge did was act as an error sink since the value
95 // had to already be undefined.
96 ExplodedNode *PrevN = *N->pred_begin();
97 ProgramPoint P = PrevN->getLocation();
98 const GRState* St = N->getState();
99
100 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
101 if (PS->getStmt() == Ex)
102 St = PrevN->getState();
103
104 FindUndefExpr FindIt(Eng.getStateManager(), St);
105 Ex = FindIt.FindExpr(Ex);
Ted Kremenek616cf052009-11-23 18:12:03 +0000106
107 // Emit the bug report.
108 EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N);
109 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
Zhongxing Xuf155dbf2009-11-23 03:29:59 +0000110 R->addRange(Ex->getSourceRange());
111
Zhongxing Xu0835e4c2009-11-23 03:20:54 +0000112 Eng.getBugReporter().EmitReport(R);
113 }
114
115 Builder.markInfeasible(true);
116 Builder.markInfeasible(false);
117 }
118}