clang  14.0.0git
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 = 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 = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N);
112  if (ex) {
113  R->addRange(ex->getSourceRange());
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 CheckerManager &mgr) {
124  return true;
125 }
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::UnaryOperator
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2157
U
BuiltinCheckerRegistration.h
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3803
CheckerManager.h
llvm::SmallString< 128 >
clang::VarDecl
Represents a variable declaration or definition.
Definition: Decl.h:876
clang::ento::bugreporter::trackExpressionValue
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
BugType.h
clang::VarDecl::getInit
const Expr * getInit() const
Definition: Decl.h:1285
CheckerContext.h
clang::DeclStmt
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1292
Checker.h
clang
Definition: CalledOnceCheck.h:17
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:69
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1856
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...