Coverage Report

Created: 2019-07-24 05:18

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