clang: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
22#include
23
24using namespace clang;
26
27namespace {
28
29
30class LocField final : public FieldNode {
31
32 const bool IsDereferenced;
33
34public:
35 LocField(const FieldRegion *FR, const bool IsDereferenced = true)
36 : FieldNode(FR), IsDereferenced(IsDereferenced) {}
37
38 void printNoteMsg(llvm::raw_ostream &Out) const override {
39 if (IsDereferenced)
40 Out << "uninitialized pointee ";
41 else
42 Out << "uninitialized pointer ";
43 }
44
45 void printPrefix(llvm::raw_ostream &Out) const override {}
46
47 void printNode(llvm::raw_ostream &Out) const override {
49 }
50
51 void printSeparator(llvm::raw_ostream &Out) const override {
52 if (getDecl()->getType()->isPointerType())
53 Out << "->";
54 else
55 Out << '.';
56 }
57};
58
59
60
61class NeedsCastLocField final : public FieldNode {
63
64public:
67
68 void printNoteMsg(llvm::raw_ostream &Out) const override {
69 Out << "uninitialized pointee ";
70 }
71
72 void printPrefix(llvm::raw_ostream &Out) const override {
73
74 if (getDecl()->getType()->isIntegerType())
75 Out << "reinterpret_cast";
76
77 else
78 Out << "static_cast";
79 Out << '<' << CastBackType.getAsString() << ">(";
80 }
81
82 void printNode(llvm::raw_ostream &Out) const override {
84 }
85
86 void printSeparator(llvm::raw_ostream &Out) const override { Out << "->"; }
87};
88
89
90class CyclicLocField final : public FieldNode {
91
92public:
94
95 void printNoteMsg(llvm::raw_ostream &Out) const override {
96 Out << "object references itself ";
97 }
98
99 void printPrefix(llvm::raw_ostream &Out) const override {}
100
101 void printNode(llvm::raw_ostream &Out) const override {
103 }
104
105 void printSeparator(llvm::raw_ostream &Out) const override {
106 llvm_unreachable("CyclicLocField objects must be the last node of the "
107 "fieldchain!");
108 }
109};
110
111}
112
113
114
121};
122
123
124
125
128
129
130
132
133
134
135
136
137bool FindUninitializedFields::isDereferencableUninit(
139
140 SVal V = State->getSVal(FR);
141
143 isanonloc::LocAsInteger(V)) &&
144 "This method only checks dereferenceable objects!");
145
146 if (V.isUnknown() || isaloc::ConcreteInt(V)) {
147 IsAnyFieldInitialized = true;
148 return false;
149 }
150
151 if (V.isUndef()) {
152 return addFieldToUninits(
153 LocalChain.add(LocField(FR, false)), FR);
154 }
155
157 IsAnyFieldInitialized = true;
158 return false;
159 }
160
161
162
163 std::optional DerefInfo = dereference(State, FR);
164 if (!DerefInfo) {
165 IsAnyFieldInitialized = true;
166 return false;
167 }
168
169 if (DerefInfo->IsCyclic)
170 return addFieldToUninits(LocalChain.add(CyclicLocField(FR)), FR);
171
173 const bool NeedsCastBack = DerefInfo->NeedsCastBack;
174
177
179 if (NeedsCastBack)
180 return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT)));
181 return isNonUnionUninit(R, LocalChain.add(LocField(FR)));
182 }
183
185 if (isUnionUninit(R)) {
186 if (NeedsCastBack)
187 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)),
188 R);
189 return addFieldToUninits(LocalChain.add(LocField(FR)), R);
190 } else {
191 IsAnyFieldInitialized = true;
192 return false;
193 }
194 }
195
197 IsAnyFieldInitialized = true;
198 return false;
199 }
200
202 "At this point FR must either have a primitive dynamic type, or it "
203 "must be a null, undefined, unknown or concrete pointer!");
204
205 SVal PointeeV = State->getSVal(R);
206
207 if (isPrimitiveUninit(PointeeV)) {
208 if (NeedsCastBack)
209 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT)), R);
210 return addFieldToUninits(LocalChain.add(LocField(FR)), R);
211 }
212
213 IsAnyFieldInitialized = true;
214 return false;
215}
216
217
218
219
220
223
224 llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;
225
226 SVal V = State->getSVal(FR);
227 assert(V.getAsRegion() && "V must have an underlying region!");
228
229
230
231
232 bool NeedsCastBack =
234
235
237 if (!R)
238 return std::nullopt;
239
240 VisitedRegions.insert(R);
241
242
244
245 while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) {
246
248 if (!R)
249 return std::nullopt;
250
251
252 if (!VisitedRegions.insert(R).second)
253 return DereferenceInfo{R, NeedsCastBack, true};
254
256
257
259 break;
260 }
261
262 while (isa(R)) {
263 NeedsCastBack = true;
264 const auto *SuperR = dyn_cast(R->getSuperRegion());
265 if (!SuperR)
266 break;
267
268 R = SuperR;
269 }
270
271 return DereferenceInfo{R, NeedsCastBack, false};
272}
273
275 while (.isNull()) {
277 return true;
279 }
280 return false;
281}
static std::optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...
static bool isVoidPointer(QualType T)
Returns whether T can be (transitively) dereferenced to a void pointer type (void*,...
A (possibly-)qualified type.
bool isVoidPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isStructureOrClassType() const
Represents a field chain.
FieldChainInfo add(const FieldNodeT &FN)
Constructs a new FieldChainInfo object with FN appended.
A lightweight polymorphic wrapper around FieldRegion *.
virtual void printSeparator(llvm::raw_ostream &Out) const =0
Print the separator.
virtual void printPrefix(llvm::raw_ostream &Out) const =0
Print any prefixes before the fieldchain. Could contain casts, etc.
virtual void printNoteMsg(llvm::raw_ostream &Out) const =0
If this is the last element of the fieldchain, this method will print the note message associated wit...
const FieldDecl * getDecl() const
virtual void printNode(llvm::raw_ostream &Out) const =0
Print the node. Should contain the name of the field stored in FR.
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
MemRegion - The root abstract class for all memory regions.
const RegionTy * getAs() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
TypedValueRegion - An abstract class representing regions having a typed value.
QualType getLocationType() const override
std::string getVariableName(const FieldDecl *Field)
Returns with Field's name.
bool isPrimitiveType(const QualType &T)
Returns true if T is a primitive type.
bool isDereferencableType(const QualType &T)
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)
const TypedValueRegion * R
bool CheckPointeeInitialization