clang  7.0.0svn
UndefinedAssignmentChecker.cpp
Go to the documentation of this file.
1 //===--- UndefinedAssignmentChecker.h ---------------------------*- 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 UndefinedAssignmentChecker, a builtin check in ExprEngine that
11 // checks for assigning undefined values.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ClangSACheckers.h"
20 
21 using namespace clang;
22 using namespace ento;
23 
24 namespace {
25 class UndefinedAssignmentChecker
26  : public Checker<check::Bind> {
27  mutable std::unique_ptr<BugType> BT;
28 
29 public:
30  void checkBind(SVal location, SVal val, const Stmt *S,
31  CheckerContext &C) const;
32 };
33 }
34 
35 void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
36  const Stmt *StoreE,
37  CheckerContext &C) const {
38  if (!val.isUndef())
39  return;
40 
41  // Do not report assignments of uninitialized values inside swap functions.
42  // This should allow to swap partially uninitialized structs
43  // (radar://14129997)
44  if (const FunctionDecl *EnclosingFunctionDecl =
45  dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
46  if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
47  return;
48 
50 
51  if (!N)
52  return;
53 
54  static const char *const DefaultMsg =
55  "Assigned value is garbage or undefined";
56  if (!BT)
57  BT.reset(new BuiltinBug(this, DefaultMsg));
58 
59  // Generate a report for this bug.
61  llvm::raw_svector_ostream OS(Str);
62 
63  const Expr *ex = nullptr;
64 
65  while (StoreE) {
66  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
67  OS << "The expression is an uninitialized value. "
68  "The computed value will also be garbage";
69 
70  ex = U->getSubExpr();
71  break;
72  }
73 
74  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
75  if (B->isCompoundAssignmentOp()) {
76  if (C.getSVal(B->getLHS()).isUndef()) {
77  OS << "The left expression of the compound assignment is an "
78  "uninitialized value. The computed value will also be garbage";
79  ex = B->getLHS();
80  break;
81  }
82  }
83 
84  ex = B->getRHS();
85  break;
86  }
87 
88  if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
89  const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
90  ex = VD->getInit();
91  }
92 
93  if (const auto *CD =
94  dyn_cast<CXXConstructorDecl>(C.getStackFrame()->getDecl())) {
95  if (CD->isImplicit()) {
96  for (auto I : CD->inits()) {
97  if (I->getInit()->IgnoreImpCasts() == StoreE) {
98  OS << "Value assigned to field '" << I->getMember()->getName()
99  << "' in implicit constructor is garbage or undefined";
100  break;
101  }
102  }
103  }
104  }
105 
106  break;
107  }
108 
109  if (OS.str().empty())
110  OS << DefaultMsg;
111 
112  auto R = llvm::make_unique<BugReport>(*BT, OS.str(), N);
113  if (ex) {
114  R->addRange(ex->getSourceRange());
116  }
117  C.emitReport(std::move(R));
118 }
119 
120 void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
121  mgr.registerChecker<UndefinedAssignmentChecker>();
122 }
Represents a function declaration or definition.
Definition: Decl.h:1714
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Stmt - This represents one statement.
Definition: Stmt.h:66
Represents a variable declaration or definition.
Definition: Decl.h:812
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
StringRef getCalleeName(const FunctionDecl *FunDecl) const
Get the name of the called function (path-sensitive).
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3016
Expr - This represents one expression.
Definition: Expr.h:106
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:1733
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:499
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
Dataflow Directional Tag Classes.
const Expr * getInit() const
Definition: Decl.h:1217
const Decl * getDecl() const
const StackFrameContext * getStackFrame() const
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
bool isUndef() const
Definition: SVals.h:141