clang  6.0.0svn
BoolAssignmentChecker.cpp
Go to the documentation of this file.
1 //== BoolAssignmentChecker.cpp - Boolean assignment checker -----*- 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 defines BoolAssignmentChecker, a builtin check in ExprEngine that
11 // performs checks for assignment of non-Boolean values to Boolean variables.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ClangSACheckers.h"
20 
21 using namespace clang;
22 using namespace ento;
23 
24 namespace {
25  class BoolAssignmentChecker : public Checker< check::Bind > {
26  mutable std::unique_ptr<BuiltinBug> BT;
27  void emitReport(ProgramStateRef state, CheckerContext &C) const;
28  public:
29  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
30  };
31 } // end anonymous namespace
32 
33 void BoolAssignmentChecker::emitReport(ProgramStateRef state,
34  CheckerContext &C) const {
35  if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
36  if (!BT)
37  BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
38  C.emitReport(llvm::make_unique<BugReport>(*BT, BT->getDescription(), N));
39  }
40 }
41 
42 static bool isBooleanType(QualType Ty) {
43  if (Ty->isBooleanType()) // C++ or C99
44  return true;
45 
46  if (const TypedefType *TT = Ty->getAs<TypedefType>())
47  return TT->getDecl()->getName() == "BOOL" || // Objective-C
48  TT->getDecl()->getName() == "_Bool" || // stdbool.h < C99
49  TT->getDecl()->getName() == "Boolean"; // MacTypes.h
50 
51  return false;
52 }
53 
54 void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
55  CheckerContext &C) const {
56 
57  // We are only interested in stores into Booleans.
58  const TypedValueRegion *TR =
59  dyn_cast_or_null<TypedValueRegion>(loc.getAsRegion());
60 
61  if (!TR)
62  return;
63 
64  QualType valTy = TR->getValueType();
65 
66  if (!isBooleanType(valTy))
67  return;
68 
69  // Get the value of the right-hand side. We only care about values
70  // that are defined (UnknownVals and UndefinedVals are handled by other
71  // checkers).
73  if (!DV)
74  return;
75 
76  // Check if the assigned value meets our criteria for correctness. It must
77  // be a value that is either 0 or 1. One way to check this is to see if
78  // the value is possibly < 0 (for a negative value) or greater than 1.
79  ProgramStateRef state = C.getState();
80  SValBuilder &svalBuilder = C.getSValBuilder();
82 
83  // First, ensure that the value is >= 0.
84  DefinedSVal zeroVal = svalBuilder.makeIntVal(0, valTy);
85  SVal greaterThanOrEqualToZeroVal =
86  svalBuilder.evalBinOp(state, BO_GE, *DV, zeroVal,
87  svalBuilder.getConditionType());
88 
89  Optional<DefinedSVal> greaterThanEqualToZero =
90  greaterThanOrEqualToZeroVal.getAs<DefinedSVal>();
91 
92  if (!greaterThanEqualToZero) {
93  // The SValBuilder cannot construct a valid SVal for this condition.
94  // This means we cannot properly reason about it.
95  return;
96  }
97 
98  ProgramStateRef stateLT, stateGE;
99  std::tie(stateGE, stateLT) = CM.assumeDual(state, *greaterThanEqualToZero);
100 
101  // Is it possible for the value to be less than zero?
102  if (stateLT) {
103  // It is possible for the value to be less than zero. We only
104  // want to emit a warning, however, if that value is fully constrained.
105  // If it it possible for the value to be >= 0, then essentially the
106  // value is underconstrained and there is nothing left to be done.
107  if (!stateGE)
108  emitReport(stateLT, C);
109 
110  // In either case, we are done.
111  return;
112  }
113 
114  // If we reach here, it must be the case that the value is constrained
115  // to only be >= 0.
116  assert(stateGE == state);
117 
118  // At this point we know that the value is >= 0.
119  // Now check to ensure that the value is <= 1.
120  DefinedSVal OneVal = svalBuilder.makeIntVal(1, valTy);
121  SVal lessThanEqToOneVal =
122  svalBuilder.evalBinOp(state, BO_LE, *DV, OneVal,
123  svalBuilder.getConditionType());
124 
125  Optional<DefinedSVal> lessThanEqToOne =
126  lessThanEqToOneVal.getAs<DefinedSVal>();
127 
128  if (!lessThanEqToOne) {
129  // The SValBuilder cannot construct a valid SVal for this condition.
130  // This means we cannot properly reason about it.
131  return;
132  }
133 
134  ProgramStateRef stateGT, stateLE;
135  std::tie(stateLE, stateGT) = CM.assumeDual(state, *lessThanEqToOne);
136 
137  // Is it possible for the value to be greater than one?
138  if (stateGT) {
139  // It is possible for the value to be greater than one. We only
140  // want to emit a warning, however, if that value is fully constrained.
141  // If it is possible for the value to be <= 1, then essentially the
142  // value is underconstrained and there is nothing left to be done.
143  if (!stateLE)
144  emitReport(stateGT, C);
145 
146  // In either case, we are done.
147  return;
148  }
149 
150  // If we reach here, it must be the case that the value is constrained
151  // to only be <= 1.
152  assert(stateLE == state);
153 }
154 
155 void ento::registerBoolAssignmentChecker(CheckerManager &mgr) {
156  mgr.registerChecker<BoolAssignmentChecker>();
157 }
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:511
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:254
A (possibly-)qualified type.
Definition: Type.h:614
Stmt - This represents one statement.
Definition: Stmt.h:60
virtual QualType getValueType() const =0
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6099
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
static bool isBooleanType(QualType Ty)
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false...
QualType getConditionType() const
Definition: SValBuilder.h:136
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:100
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
const MemRegion * getAsRegion() const
Definition: SVals.cpp:140
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:63
Dataflow Directional Tag Classes.
bool isBooleanType() const
Definition: Type.h:6026
const ProgramStateRef & getState() const
SValBuilder & getSValBuilder()