clang  8.0.0
UninitializedPointee.cpp
Go to the documentation of this file.
1 //===----- UninitializedPointee.cpp ------------------------------*- 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 file defines functions and methods for handling pointers and references
11 // to reduce the size and complexity of UninitializedObjectChecker.cpp.
12 //
13 // To read about command line options and documentation about how the checker
14 // works, refer to UninitializedObjectChecker.h.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "UninitializedObject.h"
23 
24 using namespace clang;
25 using namespace clang::ento;
26 
27 namespace {
28 
29 /// Represents a pointer or a reference field.
30 class LocField final : public FieldNode {
31  /// We'll store whether the pointee or the pointer itself is uninitialited.
32  const bool IsDereferenced;
33 
34 public:
35  LocField(const FieldRegion *FR, const bool IsDereferenced = true)
36  : FieldNode(FR), IsDereferenced(IsDereferenced) {}
37 
38  virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
39  if (IsDereferenced)
40  Out << "uninitialized pointee ";
41  else
42  Out << "uninitialized pointer ";
43  }
44 
45  virtual void printPrefix(llvm::raw_ostream &Out) const override {}
46 
47  virtual void printNode(llvm::raw_ostream &Out) const override {
48  Out << getVariableName(getDecl());
49  }
50 
51  virtual void printSeparator(llvm::raw_ostream &Out) const override {
52  if (getDecl()->getType()->isPointerType())
53  Out << "->";
54  else
55  Out << '.';
56  }
57 };
58 
59 /// Represents a nonloc::LocAsInteger or void* field, that point to objects, but
60 /// needs to be casted back to its dynamic type for a correct note message.
61 class NeedsCastLocField final : public FieldNode {
62  QualType CastBackType;
63 
64 public:
65  NeedsCastLocField(const FieldRegion *FR, const QualType &T)
66  : FieldNode(FR), CastBackType(T) {}
67 
68  virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
69  Out << "uninitialized pointee ";
70  }
71 
72  virtual void printPrefix(llvm::raw_ostream &Out) const override {
73  // If this object is a nonloc::LocAsInteger.
74  if (getDecl()->getType()->isIntegerType())
75  Out << "reinterpret_cast";
76  // If this pointer's dynamic type is different then it's static type.
77  else
78  Out << "static_cast";
79  Out << '<' << CastBackType.getAsString() << ">(";
80  }
81 
82  virtual void printNode(llvm::raw_ostream &Out) const override {
83  Out << getVariableName(getDecl()) << ')';
84  }
85 
86  virtual void printSeparator(llvm::raw_ostream &Out) const override {
87  Out << "->";
88  }
89 };
90 
91 /// Represents a Loc field that points to itself.
92 class CyclicLocField final : public FieldNode {
93 
94 public:
95  CyclicLocField(const FieldRegion *FR) : FieldNode(FR) {}
96 
97  virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
98  Out << "object references itself ";
99  }
100 
101  virtual void printPrefix(llvm::raw_ostream &Out) const override {}
102 
103  virtual void printNode(llvm::raw_ostream &Out) const override {
104  Out << getVariableName(getDecl());
105  }
106 
107  virtual void printSeparator(llvm::raw_ostream &Out) const override {
108  llvm_unreachable("CyclicLocField objects must be the last node of the "
109  "fieldchain!");
110  }
111 };
112 
113 } // end of anonymous namespace
114 
115 // Utility function declarations.
116 
119  const bool NeedsCastBack;
120  const bool IsCyclic;
121  DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)
122  : R(R), NeedsCastBack(NCB), IsCyclic(IC) {}
123 };
124 
125 /// Dereferences \p FR and returns with the pointee's region, and whether it
126 /// needs to be casted back to it's location type. If for whatever reason
127 /// dereferencing fails, returns with None.
129  const FieldRegion *FR);
130 
131 /// Returns whether \p T can be (transitively) dereferenced to a void pointer
132 /// type (void*, void**, ...).
133 static bool isVoidPointer(QualType T);
134 
135 //===----------------------------------------------------------------------===//
136 // Methods for FindUninitializedFields.
137 //===----------------------------------------------------------------------===//
138 
139 bool FindUninitializedFields::isDereferencableUninit(
140  const FieldRegion *FR, FieldChainInfo LocalChain) {
141 
142  SVal V = State->getSVal(FR);
143 
144  assert((isDereferencableType(FR->getDecl()->getType()) ||
145  V.getAs<nonloc::LocAsInteger>()) &&
146  "This method only checks dereferenceable objects!");
147 
148  if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) {
149  IsAnyFieldInitialized = true;
150  return false;
151  }
152 
153  if (V.isUndef()) {
154  return addFieldToUninits(
155  LocalChain.add(LocField(FR, /*IsDereferenced*/ false)), FR);
156  }
157 
158  if (!Opts.CheckPointeeInitialization) {
159  IsAnyFieldInitialized = true;
160  return false;
161  }
162 
163  // At this point the pointer itself is initialized and points to a valid
164  // location, we'll now check the pointee.
165  llvm::Optional<DereferenceInfo> DerefInfo = dereference(State, FR);
166  if (!DerefInfo) {
167  IsAnyFieldInitialized = true;
168  return false;
169  }
170 
171  if (DerefInfo->IsCyclic)
172  return addFieldToUninits(LocalChain.add(CyclicLocField(FR)), FR);
173 
174  const TypedValueRegion *R = DerefInfo->R;
175  const bool NeedsCastBack = DerefInfo->NeedsCastBack;
176 
177  QualType DynT = R->getLocationType();
178  QualType PointeeT = DynT->getPointeeType();
179 
180  if (PointeeT->isStructureOrClassType()) {
181  if (NeedsCastBack)
182  return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT)));
183  return isNonUnionUninit(R, LocalChain.add(LocField(FR)));
184  }
185 
186  if (PointeeT->isUnionType()) {
187  if (isUnionUninit(R)) {
188  if (NeedsCastBack)
189  return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)),
190  R);
191  return addFieldToUninits(LocalChain.add(LocField(FR)), R);
192  } else {
193  IsAnyFieldInitialized = true;
194  return false;
195  }
196  }
197 
198  if (PointeeT->isArrayType()) {
199  IsAnyFieldInitialized = true;
200  return false;
201  }
202 
203  assert((isPrimitiveType(PointeeT) || isDereferencableType(PointeeT)) &&
204  "At this point FR must either have a primitive dynamic type, or it "
205  "must be a null, undefined, unknown or concrete pointer!");
206 
207  SVal PointeeV = State->getSVal(R);
208 
209  if (isPrimitiveUninit(PointeeV)) {
210  if (NeedsCastBack)
211  return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)), R);
212  return addFieldToUninits(LocalChain.add(LocField(FR)), R);
213  }
214 
215  IsAnyFieldInitialized = true;
216  return false;
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // Utility functions.
221 //===----------------------------------------------------------------------===//
222 
224  const FieldRegion *FR) {
225 
226  llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;
227 
228  SVal V = State->getSVal(FR);
229  assert(V.getAsRegion() && "V must have an underlying region!");
230 
231  // If the static type of the field is a void pointer, or it is a
232  // nonloc::LocAsInteger, we need to cast it back to the dynamic type before
233  // dereferencing.
234  bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) ||
236 
237  // The region we'd like to acquire.
238  const auto *R = V.getAsRegion()->getAs<TypedValueRegion>();
239  if (!R)
240  return None;
241 
242  VisitedRegions.insert(R);
243 
244  // We acquire the dynamic type of R,
245  QualType DynT = R->getLocationType();
246 
247  while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) {
248 
249  R = Tmp->getAs<TypedValueRegion>();
250  if (!R)
251  return None;
252 
253  // We found a cyclic pointer, like int *ptr = (int *)&ptr.
254  if (!VisitedRegions.insert(R).second)
255  return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ true};
256 
257  DynT = R->getLocationType();
258  // In order to ensure that this loop terminates, we're also checking the
259  // dynamic type of R, since type hierarchy is finite.
261  break;
262  }
263 
264  while (R->getAs<CXXBaseObjectRegion>()) {
265  NeedsCastBack = true;
266 
267  if (!isa<TypedValueRegion>(R->getSuperRegion()))
268  break;
269  R = R->getSuperRegion()->getAs<TypedValueRegion>();
270  }
271 
272  return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ false};
273 }
274 
275 static bool isVoidPointer(QualType T) {
276  while (!T.isNull()) {
277  if (T->isVoidPointerType())
278  return true;
279  T = T->getPointeeType();
280  }
281  return false;
282 }
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:530
A (possibly-)qualified type.
Definition: Type.h:638
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
bool isArrayType() const
Definition: Type.h:6345
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:505
DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)
bool isPrimitiveType(const QualType &T)
Returns true if T is a primitive type.
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6748
LineState State
FieldChainInfo add(const FieldNodeT &FN)
Constructs a new FieldChainInfo object with FN appended.
const FieldDecl * getDecl() const
Definition: MemRegion.h:1020
static llvm::Optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee&#39;s region, and whether it needs to be casted back to it&#39;s...
bool isUnknown() const
Definition: SVals.h:137
bool isDereferencableType(const QualType &T)
const RegionTy * getAs() const
Definition: MemRegion.h:1231
std::string getVariableName(const FieldDecl *Field)
Returns with Field&#39;s name.
const TypedValueRegion * R
bool isUnionType() const
Definition: Type.cpp:475
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:703
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
bool isVoidPointerType() const
Definition: Type.cpp:469
static bool isVoidPointer(QualType T)
Returns whether T can be (transitively) dereferenced to a void pointer type (void*, void**, ...).
bool isStructureOrClassType() const
Definition: Type.cpp:461
const MemRegion * getAsRegion() const
Definition: SVals.cpp:151
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
Represents a field chain.
Dataflow Directional Tag Classes.
A lightweight polymorphic wrapper around FieldRegion *.
bool isUndef() const
Definition: SVals.h:141
QualType getType() const
Definition: Decl.h:648