clang  15.0.0git
BoolAssignmentChecker.cpp
Go to the documentation of this file.
1 //== BoolAssignmentChecker.cpp - Boolean assignment checker -----*- C++ -*--==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This defines BoolAssignmentChecker, a builtin check in ExprEngine that
10 // performs checks for assignment of non-Boolean values to Boolean variables.
11 //
12 //===----------------------------------------------------------------------===//
13 
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,
28  bool IsTainted = false) const;
29 
30  public:
31  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
32  };
33 } // end anonymous namespace
34 
35 void BoolAssignmentChecker::emitReport(ProgramStateRef state, CheckerContext &C,
36  bool IsTainted) const {
37  if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
38  if (!BT)
39  BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
40 
41  StringRef Msg = IsTainted ? "Might assign a tainted non-Boolean value"
42  : "Assignment of a non-Boolean value";
43  C.emitReport(std::make_unique<PathSensitiveBugReport>(*BT, Msg, N));
44  }
45 }
46 
47 static bool isBooleanType(QualType Ty) {
48  if (Ty->isBooleanType()) // C++ or C99
49  return true;
50 
51  if (const TypedefType *TT = Ty->getAs<TypedefType>())
52  return TT->getDecl()->getName() == "BOOL" || // Objective-C
53  TT->getDecl()->getName() == "_Bool" || // stdbool.h < C99
54  TT->getDecl()->getName() == "Boolean"; // MacTypes.h
55 
56  return false;
57 }
58 
59 void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
60  CheckerContext &C) const {
61 
62  // We are only interested in stores into Booleans.
63  const TypedValueRegion *TR =
64  dyn_cast_or_null<TypedValueRegion>(loc.getAsRegion());
65 
66  if (!TR)
67  return;
68 
69  QualType valTy = TR->getValueType();
70 
71  if (!isBooleanType(valTy))
72  return;
73 
74  // Get the value of the right-hand side. We only care about values
75  // that are defined (UnknownVals and UndefinedVals are handled by other
76  // checkers).
77  Optional<NonLoc> NV = val.getAs<NonLoc>();
78  if (!NV)
79  return;
80 
81  // Check if the assigned value meets our criteria for correctness. It must
82  // be a value that is either 0 or 1. One way to check this is to see if
83  // the value is possibly < 0 (for a negative value) or greater than 1.
84  ProgramStateRef state = C.getState();
85  SValBuilder &svalBuilder = C.getSValBuilder();
86  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
87  ConstraintManager &CM = C.getConstraintManager();
88 
89  llvm::APSInt Zero = BVF.getValue(0, valTy);
90  llvm::APSInt One = BVF.getValue(1, valTy);
91 
92  ProgramStateRef StIn, StOut;
93  std::tie(StIn, StOut) = CM.assumeInclusiveRangeDual(state, *NV, Zero, One);
94 
95  if (!StIn)
96  emitReport(StOut, C);
97  if (StIn && StOut && taint::isTainted(state, *NV))
98  emitReport(StOut, C, /*IsTainted=*/true);
99 }
100 
101 void ento::registerBoolAssignmentChecker(CheckerManager &mgr) {
102  mgr.registerChecker<BoolAssignmentChecker>();
103 }
104 
105 bool ento::shouldRegisterBoolAssignmentChecker(const CheckerManager &mgr) {
106  return true;
107 }
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:731
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:55
llvm::Optional
Definition: LLVM.h:40
clang::ento::taint::isTainted
bool isTainted(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)
Check if the statement has a tainted value in the given state.
clang::TypedefType
Definition: Type.h:4464
APSInt
llvm::APSInt APSInt
Definition: ByteCodeEmitter.cpp:19
BuiltinCheckerRegistration.h
CheckerManager.h
clang::Type::getAs
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7302
clang::interp::Zero
bool Zero(InterpState &S, CodePtr OpPC)
Definition: Interp.h:814
state
and static some checkers Checker The latter are built on top of the former via the Checker and CheckerVisitor and attempts to isolate them from much of the gore of the internal analysis the analyzer is basically a source code simulator that traces out possible paths of execution The state of the and the combination of state and program point is a node in an exploded which has the entry program point and initial state
Definition: README.txt:30
Taint.h
BugType.h
isBooleanType
static bool isBooleanType(QualType Ty)
Definition: BoolAssignmentChecker.cpp:47
CheckerContext.h
clang::Type::isBooleanType
bool isBooleanType() const
Definition: Type.h:7212
Checker.h
clang
Definition: CalledOnceCheck.h:17
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:70