/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/Store.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Store.cpp - Interface for maps from Locations to Values ------------===// |
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 defined the types Store and StoreManager. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" |
14 | | #include "clang/AST/ASTContext.h" |
15 | | #include "clang/AST/CXXInheritance.h" |
16 | | #include "clang/AST/CharUnits.h" |
17 | | #include "clang/AST/Decl.h" |
18 | | #include "clang/AST/DeclCXX.h" |
19 | | #include "clang/AST/DeclObjC.h" |
20 | | #include "clang/AST/Expr.h" |
21 | | #include "clang/AST/Type.h" |
22 | | #include "clang/Basic/LLVM.h" |
23 | | #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" |
24 | | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
25 | | #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" |
26 | | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" |
27 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" |
28 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
29 | | #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" |
30 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" |
31 | | #include "llvm/ADT/APSInt.h" |
32 | | #include "llvm/ADT/Optional.h" |
33 | | #include "llvm/ADT/SmallVector.h" |
34 | | #include "llvm/Support/Casting.h" |
35 | | #include "llvm/Support/ErrorHandling.h" |
36 | | #include <cassert> |
37 | | #include <cstdint> |
38 | | |
39 | | using namespace clang; |
40 | | using namespace ento; |
41 | | |
42 | | StoreManager::StoreManager(ProgramStateManager &stateMgr) |
43 | | : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), |
44 | 13.8k | MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} |
45 | | |
46 | | StoreRef StoreManager::enterStackFrame(Store OldStore, |
47 | | const CallEvent &Call, |
48 | 33.8k | const StackFrameContext *LCtx) { |
49 | 33.8k | StoreRef Store = StoreRef(OldStore, *this); |
50 | | |
51 | 33.8k | SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings; |
52 | 33.8k | Call.getInitialStackFrameContents(LCtx, InitialBindings); |
53 | | |
54 | 33.8k | for (const auto &I : InitialBindings) |
55 | 38.9k | Store = Bind(Store.getStore(), I.first.castAs<Loc>(), I.second); |
56 | | |
57 | 33.8k | return Store; |
58 | 33.8k | } |
59 | | |
60 | | const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base, |
61 | | QualType EleTy, |
62 | 7.12k | uint64_t index) { |
63 | 7.12k | NonLoc idx = svalBuilder.makeArrayIndex(index); |
64 | 7.12k | return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); |
65 | 7.12k | } |
66 | | |
67 | | const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R, |
68 | 7.95k | QualType T) { |
69 | 7.95k | NonLoc idx = svalBuilder.makeZeroArrayIndex(); |
70 | 7.95k | assert(!T.isNull()); |
71 | 0 | return MRMgr.getElementRegion(T, idx, R, Ctx); |
72 | 7.95k | } |
73 | | |
74 | 8.89k | const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) { |
75 | 8.89k | ASTContext &Ctx = StateMgr.getContext(); |
76 | | |
77 | | // Handle casts to Objective-C objects. |
78 | 8.89k | if (CastToTy->isObjCObjectPointerType()) |
79 | 1.21k | return R->StripCasts(); |
80 | | |
81 | 7.68k | if (CastToTy->isBlockPointerType()) { |
82 | | // FIXME: We may need different solutions, depending on the symbol |
83 | | // involved. Blocks can be casted to/from 'id', as they can be treated |
84 | | // as Objective-C objects. This could possibly be handled by enhancing |
85 | | // our reasoning of downcasts of symbolic objects. |
86 | 3 | if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R)) |
87 | 2 | return R; |
88 | | |
89 | | // We don't know what to make of it. Return a NULL region, which |
90 | | // will be interpreted as UnknownVal. |
91 | 1 | return nullptr; |
92 | 3 | } |
93 | | |
94 | | // Now assume we are casting from pointer to pointer. Other cases should |
95 | | // already be handled. |
96 | 7.67k | QualType PointeeTy = CastToTy->getPointeeType(); |
97 | 7.67k | QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); |
98 | | |
99 | | // Handle casts to void*. We just pass the region through. |
100 | 7.67k | if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy) |
101 | 196 | return R; |
102 | | |
103 | | // Handle casts from compatible types. |
104 | 7.48k | if (R->isBoundable()) |
105 | 7.48k | if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { |
106 | 2.01k | QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); |
107 | 2.01k | if (CanonPointeeTy == ObjTy) |
108 | 361 | return R; |
109 | 2.01k | } |
110 | | |
111 | | // Process region cast according to the kind of the region being cast. |
112 | 7.12k | switch (R->getKind()) { |
113 | 0 | case MemRegion::CXXThisRegionKind: |
114 | 0 | case MemRegion::CodeSpaceRegionKind: |
115 | 0 | case MemRegion::StackLocalsSpaceRegionKind: |
116 | 0 | case MemRegion::StackArgumentsSpaceRegionKind: |
117 | 0 | case MemRegion::HeapSpaceRegionKind: |
118 | 0 | case MemRegion::UnknownSpaceRegionKind: |
119 | 0 | case MemRegion::StaticGlobalSpaceRegionKind: |
120 | 0 | case MemRegion::GlobalInternalSpaceRegionKind: |
121 | 0 | case MemRegion::GlobalSystemSpaceRegionKind: |
122 | 0 | case MemRegion::GlobalImmutableSpaceRegionKind: { |
123 | 0 | llvm_unreachable("Invalid region cast"); |
124 | 0 | } |
125 | | |
126 | 2 | case MemRegion::FunctionCodeRegionKind: |
127 | 2 | case MemRegion::BlockCodeRegionKind: |
128 | 2 | case MemRegion::BlockDataRegionKind: |
129 | 2 | case MemRegion::StringRegionKind: |
130 | | // FIXME: Need to handle arbitrary downcasts. |
131 | 5.44k | case MemRegion::SymbolicRegionKind: |
132 | 5.46k | case MemRegion::AllocaRegionKind: |
133 | 5.46k | case MemRegion::CompoundLiteralRegionKind: |
134 | 5.56k | case MemRegion::FieldRegionKind: |
135 | 5.57k | case MemRegion::ObjCIvarRegionKind: |
136 | 5.57k | case MemRegion::ObjCStringRegionKind: |
137 | 6.58k | case MemRegion::NonParamVarRegionKind: |
138 | 6.58k | case MemRegion::ParamVarRegionKind: |
139 | 6.66k | case MemRegion::CXXTempObjectRegionKind: |
140 | 6.67k | case MemRegion::CXXBaseObjectRegionKind: |
141 | 6.67k | case MemRegion::CXXDerivedObjectRegionKind: |
142 | 6.67k | return MakeElementRegion(cast<SubRegion>(R), PointeeTy); |
143 | | |
144 | 450 | case MemRegion::ElementRegionKind: { |
145 | | // If we are casting from an ElementRegion to another type, the |
146 | | // algorithm is as follows: |
147 | | // |
148 | | // (1) Compute the "raw offset" of the ElementRegion from the |
149 | | // base region. This is done by calling 'getAsRawOffset()'. |
150 | | // |
151 | | // (2a) If we get a 'RegionRawOffset' after calling |
152 | | // 'getAsRawOffset()', determine if the absolute offset |
153 | | // can be exactly divided into chunks of the size of the |
154 | | // casted-pointee type. If so, create a new ElementRegion with |
155 | | // the pointee-cast type as the new ElementType and the index |
156 | | // being the offset divded by the chunk size. If not, create |
157 | | // a new ElementRegion at offset 0 off the raw offset region. |
158 | | // |
159 | | // (2b) If we don't a get a 'RegionRawOffset' after calling |
160 | | // 'getAsRawOffset()', it means that we are at offset 0. |
161 | | // |
162 | | // FIXME: Handle symbolic raw offsets. |
163 | | |
164 | 450 | const ElementRegion *elementR = cast<ElementRegion>(R); |
165 | 450 | const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); |
166 | 450 | const MemRegion *baseR = rawOff.getRegion(); |
167 | | |
168 | | // If we cannot compute a raw offset, throw up our hands and return |
169 | | // a NULL MemRegion*. |
170 | 450 | if (!baseR) |
171 | 13 | return nullptr; |
172 | | |
173 | 437 | CharUnits off = rawOff.getOffset(); |
174 | | |
175 | 437 | if (off.isZero()) { |
176 | | // Edge case: we are at 0 bytes off the beginning of baseR. We |
177 | | // check to see if type we are casting to is the same as the base |
178 | | // region. If so, just return the base region. |
179 | 178 | if (const auto *TR = dyn_cast<TypedValueRegion>(baseR)) { |
180 | 101 | QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); |
181 | 101 | QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); |
182 | 101 | if (CanonPointeeTy == ObjTy) |
183 | 6 | return baseR; |
184 | 101 | } |
185 | | |
186 | | // Otherwise, create a new ElementRegion at offset 0. |
187 | 172 | return MakeElementRegion(cast<SubRegion>(baseR), PointeeTy); |
188 | 178 | } |
189 | | |
190 | | // We have a non-zero offset from the base region. We want to determine |
191 | | // if the offset can be evenly divided by sizeof(PointeeTy). If so, |
192 | | // we create an ElementRegion whose index is that value. Otherwise, we |
193 | | // create two ElementRegions, one that reflects a raw offset and the other |
194 | | // that reflects the cast. |
195 | | |
196 | | // Compute the index for the new ElementRegion. |
197 | 259 | int64_t newIndex = 0; |
198 | 259 | const MemRegion *newSuperR = nullptr; |
199 | | |
200 | | // We can only compute sizeof(PointeeTy) if it is a complete type. |
201 | 259 | if (!PointeeTy->isIncompleteType()) { |
202 | | // Compute the size in **bytes**. |
203 | 257 | CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy); |
204 | 257 | if (!pointeeTySize.isZero()) { |
205 | | // Is the offset a multiple of the size? If so, we can layer the |
206 | | // ElementRegion (with elementType == PointeeTy) directly on top of |
207 | | // the base region. |
208 | 255 | if (off % pointeeTySize == 0) { |
209 | 237 | newIndex = off / pointeeTySize; |
210 | 237 | newSuperR = baseR; |
211 | 237 | } |
212 | 255 | } |
213 | 257 | } |
214 | | |
215 | 259 | if (!newSuperR) { |
216 | | // Create an intermediate ElementRegion to represent the raw byte. |
217 | | // This will be the super region of the final ElementRegion. |
218 | 22 | newSuperR = MakeElementRegion(cast<SubRegion>(baseR), Ctx.CharTy, |
219 | 22 | off.getQuantity()); |
220 | 22 | } |
221 | | |
222 | 259 | return MakeElementRegion(cast<SubRegion>(newSuperR), PointeeTy, newIndex); |
223 | 437 | } |
224 | 7.12k | } |
225 | | |
226 | 7.12k | llvm_unreachable0 ("unreachable"); |
227 | 7.12k | } |
228 | | |
229 | 835 | static bool regionMatchesCXXRecordType(SVal V, QualType Ty) { |
230 | 835 | const MemRegion *MR = V.getAsRegion(); |
231 | 835 | if (!MR) |
232 | 7 | return true; |
233 | | |
234 | 828 | const auto *TVR = dyn_cast<TypedValueRegion>(MR); |
235 | 828 | if (!TVR) |
236 | 234 | return true; |
237 | | |
238 | 594 | const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl(); |
239 | 594 | if (!RD) |
240 | 0 | return true; |
241 | | |
242 | 594 | const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl(); |
243 | 594 | if (!Expected) |
244 | 429 | Expected = Ty->getAsCXXRecordDecl(); |
245 | | |
246 | 594 | return Expected->getCanonicalDecl() == RD->getCanonicalDecl(); |
247 | 594 | } |
248 | | |
249 | 835 | SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { |
250 | | // Sanity check to avoid doing the wrong thing in the face of |
251 | | // reinterpret_cast. |
252 | 835 | if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType())) |
253 | 1 | return UnknownVal(); |
254 | | |
255 | | // Walk through the cast path to create nested CXXBaseRegions. |
256 | 834 | SVal Result = Derived; |
257 | 834 | for (CastExpr::path_const_iterator I = Cast->path_begin(), |
258 | 834 | E = Cast->path_end(); |
259 | 1.76k | I != E; ++I931 ) { |
260 | 931 | Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual()); |
261 | 931 | } |
262 | 834 | return Result; |
263 | 835 | } |
264 | | |
265 | 10 | SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { |
266 | | // Walk through the path to create nested CXXBaseRegions. |
267 | 10 | SVal Result = Derived; |
268 | 10 | for (const auto &I : Path) |
269 | 12 | Result = evalDerivedToBase(Result, I.Base->getType(), |
270 | 12 | I.Base->isVirtual()); |
271 | 10 | return Result; |
272 | 10 | } |
273 | | |
274 | | SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, |
275 | 1.82k | bool IsVirtual) { |
276 | 1.82k | const MemRegion *DerivedReg = Derived.getAsRegion(); |
277 | 1.82k | if (!DerivedReg) |
278 | 11 | return Derived; |
279 | | |
280 | 1.81k | const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl(); |
281 | 1.81k | if (!BaseDecl) |
282 | 1.81k | BaseDecl = BaseType->getAsCXXRecordDecl(); |
283 | 1.81k | assert(BaseDecl && "not a C++ object?"); |
284 | | |
285 | 1.81k | if (const auto *AlreadyDerivedReg = |
286 | 13 | dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) { |
287 | 13 | if (const auto *SR = |
288 | 13 | dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion())) |
289 | 13 | if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl) |
290 | 10 | return loc::MemRegionVal(SR); |
291 | | |
292 | 3 | DerivedReg = AlreadyDerivedReg->getSuperRegion(); |
293 | 3 | } |
294 | | |
295 | 1.80k | const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion( |
296 | 1.80k | BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual); |
297 | | |
298 | 1.80k | return loc::MemRegionVal(BaseReg); |
299 | 1.81k | } |
300 | | |
301 | | /// Returns the static type of the given region, if it represents a C++ class |
302 | | /// object. |
303 | | /// |
304 | | /// This handles both fully-typed regions, where the dynamic type is known, and |
305 | | /// symbolic regions, where the dynamic type is merely bounded (and even then, |
306 | | /// only ostensibly!), but does not take advantage of any dynamic type info. |
307 | 262 | static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) { |
308 | 262 | if (const auto *TVR = dyn_cast<TypedValueRegion>(MR)) |
309 | 174 | return TVR->getValueType()->getAsCXXRecordDecl(); |
310 | 88 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) |
311 | 88 | return SR->getSymbol()->getType()->getPointeeCXXRecordDecl(); |
312 | 0 | return nullptr; |
313 | 88 | } |
314 | | |
315 | | SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, |
316 | 139 | bool &Failed) { |
317 | 139 | Failed = false; |
318 | | |
319 | 139 | const MemRegion *MR = Base.getAsRegion(); |
320 | 139 | if (!MR) |
321 | 0 | return UnknownVal(); |
322 | | |
323 | | // Assume the derived class is a pointer or a reference to a CXX record. |
324 | 139 | TargetType = TargetType->getPointeeType(); |
325 | 139 | assert(!TargetType.isNull()); |
326 | 0 | const CXXRecordDecl *TargetClass = TargetType->getAsCXXRecordDecl(); |
327 | 139 | if (!TargetClass && !TargetType->isVoidType()1 ) |
328 | 0 | return UnknownVal(); |
329 | | |
330 | | // Drill down the CXXBaseObject chains, which represent upcasts (casts from |
331 | | // derived to base). |
332 | 262 | while (const CXXRecordDecl *139 MRClass = getCXXRecordType(MR)) { |
333 | | // If found the derived class, the cast succeeds. |
334 | 260 | if (MRClass == TargetClass) |
335 | 91 | return loc::MemRegionVal(MR); |
336 | | |
337 | | // We skip over incomplete types. They must be the result of an earlier |
338 | | // reinterpret_cast, as one can only dynamic_cast between types in the same |
339 | | // class hierarchy. |
340 | 169 | if (!TargetType->isVoidType() && MRClass->hasDefinition()168 ) { |
341 | | // Static upcasts are marked as DerivedToBase casts by Sema, so this will |
342 | | // only happen when multiple or virtual inheritance is involved. |
343 | 165 | CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, |
344 | 165 | /*DetectVirtual=*/false); |
345 | 165 | if (MRClass->isDerivedFrom(TargetClass, Paths)) |
346 | 9 | return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front()); |
347 | 165 | } |
348 | | |
349 | 160 | if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) { |
350 | | // Drill down the chain to get the derived classes. |
351 | 114 | MR = BaseR->getSuperRegion(); |
352 | 114 | continue; |
353 | 114 | } |
354 | | |
355 | | // If this is a cast to void*, return the region. |
356 | 46 | if (TargetType->isVoidType()) |
357 | 1 | return loc::MemRegionVal(MR); |
358 | | |
359 | | // Strange use of reinterpret_cast can give us paths we don't reason |
360 | | // about well, by putting in ElementRegions where we'd expect |
361 | | // CXXBaseObjectRegions. If it's a valid reinterpret_cast (i.e. if the |
362 | | // derived class has a zero offset from the base class), then it's safe |
363 | | // to strip the cast; if it's invalid, -Wreinterpret-base-class should |
364 | | // catch it. In the interest of performance, the analyzer will silently |
365 | | // do the wrong thing in the invalid case (because offsets for subregions |
366 | | // will be wrong). |
367 | 45 | const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false); |
368 | 45 | if (Uncasted == MR) { |
369 | | // We reached the bottom of the hierarchy and did not find the derived |
370 | | // class. We must be casting the base to derived, so the cast should |
371 | | // fail. |
372 | 36 | break; |
373 | 36 | } |
374 | | |
375 | 9 | MR = Uncasted; |
376 | 9 | } |
377 | | |
378 | | // If we're casting a symbolic base pointer to a derived class, use |
379 | | // CXXDerivedObjectRegion to represent the cast. If it's a pointer to an |
380 | | // unrelated type, it must be a weird reinterpret_cast and we have to |
381 | | // be fine with ElementRegion. TODO: Should we instead make |
382 | | // Derived{TargetClass, Element{SourceClass, SR}}? |
383 | 38 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) { |
384 | 26 | QualType T = SR->getSymbol()->getType(); |
385 | 26 | const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl(); |
386 | 26 | if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass)25 ) |
387 | 21 | return loc::MemRegionVal( |
388 | 21 | MRMgr.getCXXDerivedObjectRegion(TargetClass, SR)); |
389 | 5 | return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType)); |
390 | 26 | } |
391 | | |
392 | | // We failed if the region we ended up with has perfect type info. |
393 | 12 | Failed = isa<TypedValueRegion>(MR); |
394 | 12 | return UnknownVal(); |
395 | 38 | } |
396 | | |
397 | 44.1k | static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) { |
398 | 44.1k | return ty1->getPointeeType().getCanonicalType().getTypePtr() == |
399 | 44.1k | ty2->getPointeeType().getCanonicalType().getTypePtr(); |
400 | 44.1k | } |
401 | | |
402 | | /// CastRetrievedVal - Used by subclasses of StoreManager to implement |
403 | | /// implicit casts that arise from loads from regions that are reinterpreted |
404 | | /// as another region. |
405 | | SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, |
406 | 393k | QualType castTy) { |
407 | 393k | if (castTy.isNull() || V.isUnknownOrUndef()) |
408 | 83.5k | return V; |
409 | | |
410 | | // The dispatchCast() call below would convert the int into a float. |
411 | | // What we want, however, is a bit-by-bit reinterpretation of the int |
412 | | // as a float, which usually yields nothing garbage. For now skip casts |
413 | | // from ints to floats. |
414 | | // TODO: What other combinations of types are affected? |
415 | 309k | if (castTy->isFloatingType()) { |
416 | 89 | SymbolRef Sym = V.getAsSymbol(); |
417 | 89 | if (Sym && !Sym->getType()->isFloatingType()73 ) |
418 | 25 | return UnknownVal(); |
419 | 89 | } |
420 | | |
421 | | // When retrieving symbolic pointer and expecting a non-void pointer, |
422 | | // wrap them into element regions of the expected type if necessary. |
423 | | // SValBuilder::dispatchCast() doesn't do that, but it is necessary to |
424 | | // make sure that the retrieved value makes sense, because there's no other |
425 | | // cast in the AST that would tell us to cast it to the correct pointer type. |
426 | | // We might need to do that for non-void pointers as well. |
427 | | // FIXME: We really need a single good function to perform casts for us |
428 | | // correctly every time we need it. |
429 | 309k | if (castTy->isPointerType() && !castTy->isVoidPointerType()149k ) |
430 | 142k | if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) { |
431 | 44.1k | QualType sr = SR->getSymbol()->getType(); |
432 | 44.1k | if (!hasSameUnqualifiedPointeeType(sr, castTy)) |
433 | 13 | return loc::MemRegionVal(castRegion(SR, castTy)); |
434 | 44.1k | } |
435 | | |
436 | 309k | return svalBuilder.dispatchCast(V, castTy); |
437 | 309k | } |
438 | | |
439 | 55.1k | SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { |
440 | 55.1k | if (Base.isUnknownOrUndef()) |
441 | 11 | return Base; |
442 | | |
443 | 55.1k | Loc BaseL = Base.castAs<Loc>(); |
444 | 55.1k | const SubRegion* BaseR = nullptr; |
445 | | |
446 | 55.1k | switch (BaseL.getSubKind()) { |
447 | 55.0k | case loc::MemRegionValKind: |
448 | 55.0k | BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion()); |
449 | 55.0k | break; |
450 | | |
451 | 0 | case loc::GotoLabelKind: |
452 | | // These are anormal cases. Flag an undefined value. |
453 | 0 | return UndefinedVal(); |
454 | | |
455 | 64 | case loc::ConcreteIntKind: |
456 | | // While these seem funny, this can happen through casts. |
457 | | // FIXME: What we should return is the field offset, not base. For example, |
458 | | // add the field offset to the integer value. That way things |
459 | | // like this work properly: &(((struct foo *) 0xa)->f) |
460 | | // However, that's not easy to fix without reducing our abilities |
461 | | // to catch null pointer dereference. Eg., ((struct foo *)0x0)->f = 7 |
462 | | // is a null dereference even though we're dereferencing offset of f |
463 | | // rather than null. Coming up with an approach that computes offsets |
464 | | // over null pointers properly while still being able to catch null |
465 | | // dereferences might be worth it. |
466 | 64 | return Base; |
467 | | |
468 | 0 | default: |
469 | 0 | llvm_unreachable("Unhandled Base."); |
470 | 55.1k | } |
471 | | |
472 | | // NOTE: We must have this check first because ObjCIvarDecl is a subclass |
473 | | // of FieldDecl. |
474 | 55.0k | if (const auto *ID = dyn_cast<ObjCIvarDecl>(D)) |
475 | 1.45k | return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); |
476 | | |
477 | 53.5k | return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); |
478 | 55.0k | } |
479 | | |
480 | 1.47k | SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) { |
481 | 1.47k | return getLValueFieldOrIvar(decl, base); |
482 | 1.47k | } |
483 | | |
484 | | SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, |
485 | 7.96k | SVal Base) { |
486 | | // If the base is an unknown or undefined value, just return it back. |
487 | | // FIXME: For absolute pointer addresses, we just return that value back as |
488 | | // well, although in reality we should return the offset added to that |
489 | | // value. See also the similar FIXME in getLValueFieldOrIvar(). |
490 | 7.96k | if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>()7.95k ) |
491 | 68 | return Base; |
492 | | |
493 | 7.89k | if (Base.getAs<loc::GotoLabel>()) |
494 | 2 | return UnknownVal(); |
495 | | |
496 | 7.89k | const SubRegion *BaseRegion = |
497 | 7.89k | Base.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>(); |
498 | | |
499 | | // Pointer of any type can be cast and used as array base. |
500 | 7.89k | const auto *ElemR = dyn_cast<ElementRegion>(BaseRegion); |
501 | | |
502 | | // Convert the offset to the appropriate size and signedness. |
503 | 7.89k | Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>(); |
504 | | |
505 | 7.89k | if (!ElemR) { |
506 | | // If the base region is not an ElementRegion, create one. |
507 | | // This can happen in the following example: |
508 | | // |
509 | | // char *p = __builtin_alloc(10); |
510 | | // p[1] = 8; |
511 | | // |
512 | | // Observe that 'p' binds to an AllocaRegion. |
513 | 2.32k | return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, |
514 | 2.32k | BaseRegion, Ctx)); |
515 | 2.32k | } |
516 | | |
517 | 5.57k | SVal BaseIdx = ElemR->getIndex(); |
518 | | |
519 | 5.57k | if (!BaseIdx.getAs<nonloc::ConcreteInt>()) |
520 | 32 | return UnknownVal(); |
521 | | |
522 | 5.53k | const llvm::APSInt &BaseIdxI = |
523 | 5.53k | BaseIdx.castAs<nonloc::ConcreteInt>().getValue(); |
524 | | |
525 | | // Only allow non-integer offsets if the base region has no offset itself. |
526 | | // FIXME: This is a somewhat arbitrary restriction. We should be using |
527 | | // SValBuilder here to add the two offsets without checking their types. |
528 | 5.53k | if (!Offset.getAs<nonloc::ConcreteInt>()) { |
529 | 290 | if (isa<ElementRegion>(BaseRegion->StripCasts())) |
530 | 0 | return UnknownVal(); |
531 | | |
532 | 290 | return loc::MemRegionVal(MRMgr.getElementRegion( |
533 | 290 | elementType, Offset, cast<SubRegion>(ElemR->getSuperRegion()), Ctx)); |
534 | 290 | } |
535 | | |
536 | 5.24k | const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue(); |
537 | 5.24k | assert(BaseIdxI.isSigned()); |
538 | | |
539 | | // Compute the new index. |
540 | 0 | nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI + |
541 | 5.24k | OffI)); |
542 | | |
543 | | // Construct the new ElementRegion. |
544 | 5.24k | const SubRegion *ArrayR = cast<SubRegion>(ElemR->getSuperRegion()); |
545 | 5.24k | return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, |
546 | 5.24k | Ctx)); |
547 | 5.53k | } |
548 | | |
549 | 77.1k | StoreManager::BindingsHandler::~BindingsHandler() = default; |
550 | | |
551 | | bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr, |
552 | | Store store, |
553 | | const MemRegion* R, |
554 | 26.4k | SVal val) { |
555 | 26.4k | SymbolRef SymV = val.getAsLocSymbol(); |
556 | 26.4k | if (!SymV || SymV != Sym15.9k ) |
557 | 16.2k | return true; |
558 | | |
559 | 10.2k | if (Binding) { |
560 | 544 | First = false; |
561 | 544 | return false; |
562 | 544 | } |
563 | 9.70k | else |
564 | 9.70k | Binding = R; |
565 | | |
566 | 9.70k | return true; |
567 | 10.2k | } |