clang  9.0.0
UndefinedAssignmentChecker.cpp
Go to the documentation of this file.
1 //===--- UndefinedAssignmentChecker.h ---------------------------*- 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 UndefinedAssignmentChecker, a builtin check in ExprEngine that
10 // checks for assigning undefined values.
11 //
12 //===----------------------------------------------------------------------===//
13 
19 
20 using namespace clang;
21 using namespace ento;
22 
23 namespace {
24 class UndefinedAssignmentChecker
25  : public Checker<check::Bind> {
26  mutable std::unique_ptr<BugType> BT;
27 
28 public:
29  void checkBind(SVal location, SVal val, const Stmt *S,
30  CheckerContext &C) const;
31 };
32 }
33 
34 void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
35  const Stmt *StoreE,
36  CheckerContext &C) const {
37  if (!val.isUndef())
38  return;
39 
40  // Do not report assignments of uninitialized values inside swap functions.
41  // This should allow to swap partially uninitialized structs
42  // (radar://14129997)
43  if (const FunctionDecl *EnclosingFunctionDecl =
44  dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
45  if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
46  return;
47 
48  ExplodedNode *N = C.generateErrorNode();
49 
50  if (!N)
51  return;
52 
53  static const char *const DefaultMsg =
54  "Assigned value is garbage or undefined";
55  if (!BT)
56  BT.reset(new BuiltinBug(this, DefaultMsg));
57 
58  // Generate a report for this bug.
60  llvm::raw_svector_ostream OS(Str);
61 
62  const Expr *ex = nullptr;
63 
64  while (StoreE) {
65  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
66  OS << "The expression is an uninitialized value. "
67  "The computed value will also be garbage";
68 
69  ex = U->getSubExpr();
70  break;
71  }
72 
73  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
74  if (B->isCompoundAssignmentOp()) {
75  if (C.getSVal(B->getLHS()).isUndef()) {
76  OS << "The left expression of the compound assignment is an "
77  "uninitialized value. The computed value will also be garbage";
78  ex = B->getLHS();
79  break;
80  }
81  }
82 
83  ex = B->getRHS();
84  break;
85  }
86 
87  if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
88  const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
89  ex = VD->getInit();
90  }
91 
92  if (const auto *CD =
93  dyn_cast<CXXConstructorDecl>(C.getStackFrame()->getDecl())) {
94  if (CD->isImplicit()) {
95  for (auto I : CD->inits()) {
96  if (I->getInit()->IgnoreImpCasts() == StoreE) {
97  OS << "Value assigned to field '" << I->getMember()->getName()
98  << "' in implicit constructor is garbage or undefined";
99  break;
100  }
101  }
102  }
103  }
104 
105  break;
106  }
107 
108  if (OS.str().empty())
109  OS << DefaultMsg;
110 
111  auto R = llvm::make_unique<BugReport>(*BT, OS.str(), N);
112  if (ex) {
113  R->addRange(ex->getSourceRange());
114  bugreporter::trackExpressionValue(N, ex, *R);
115  }
116  C.emitReport(std::move(R));
117 }
118 
119 void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
120  mgr.registerChecker<UndefinedAssignmentChecker>();
121 }
122 
123 bool ento::shouldRegisterUndefinedAssignmentChecker(const LangOptions &LO) {
124  return true;
125 }
Represents a function declaration or definition.
Definition: Decl.h:1748
Stmt - This represents one statement.
Definition: Stmt.h:66
Represents a variable declaration or definition.
Definition: Decl.h:812
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3405
This represents one expression.
Definition: Expr.h:108
UnaryOperator - This represents the unary-expression&#39;s (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
Definition: Expr.h:2016
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:1203
Dataflow Directional Tag Classes.
const Expr * getInit() const
Definition: Decl.h:1219
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.