1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
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 | MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} |
45 | |
46 | StoreRef StoreManager::enterStackFrame(Store OldStore, |
47 | const CallEvent &Call, |
48 | const StackFrameContext *LCtx) { |
49 | StoreRef Store = StoreRef(OldStore, *this); |
50 | |
51 | SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings; |
52 | Call.getInitialStackFrameContents(LCtx, InitialBindings); |
53 | |
54 | for (const auto &I : InitialBindings) |
55 | Store = Bind(Store.getStore(), I.first, I.second); |
56 | |
57 | return Store; |
58 | } |
59 | |
60 | const ElementRegion *StoreManager::MakeElementRegion(const SubRegion *Base, |
61 | QualType EleTy, |
62 | uint64_t index) { |
63 | NonLoc idx = svalBuilder.makeArrayIndex(index); |
64 | return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); |
65 | } |
66 | |
67 | const ElementRegion *StoreManager::GetElementZeroRegion(const SubRegion *R, |
68 | QualType T) { |
69 | NonLoc idx = svalBuilder.makeZeroArrayIndex(); |
70 | assert(!T.isNull()); |
71 | return MRMgr.getElementRegion(T, idx, R, Ctx); |
72 | } |
73 | |
74 | const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) { |
75 | ASTContext &Ctx = StateMgr.getContext(); |
76 | |
77 | |
78 | if (CastToTy->isObjCObjectPointerType()) |
79 | return R->StripCasts(); |
80 | |
81 | if (CastToTy->isBlockPointerType()) { |
82 | |
83 | |
84 | |
85 | |
86 | if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R)) |
87 | return R; |
88 | |
89 | |
90 | |
91 | return nullptr; |
92 | } |
93 | |
94 | |
95 | |
96 | QualType PointeeTy = CastToTy->getPointeeType(); |
97 | QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); |
98 | |
99 | |
100 | if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy) |
101 | return R; |
102 | |
103 | |
104 | if (R->isBoundable()) |
105 | if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { |
106 | QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); |
107 | if (CanonPointeeTy == ObjTy) |
108 | return R; |
109 | } |
110 | |
111 | |
112 | switch (R->getKind()) { |
113 | case MemRegion::CXXThisRegionKind: |
114 | case MemRegion::CodeSpaceRegionKind: |
115 | case MemRegion::StackLocalsSpaceRegionKind: |
116 | case MemRegion::StackArgumentsSpaceRegionKind: |
117 | case MemRegion::HeapSpaceRegionKind: |
118 | case MemRegion::UnknownSpaceRegionKind: |
119 | case MemRegion::StaticGlobalSpaceRegionKind: |
120 | case MemRegion::GlobalInternalSpaceRegionKind: |
121 | case MemRegion::GlobalSystemSpaceRegionKind: |
122 | case MemRegion::GlobalImmutableSpaceRegionKind: { |
123 | llvm_unreachable("Invalid region cast"); |
124 | } |
125 | |
126 | case MemRegion::FunctionCodeRegionKind: |
127 | case MemRegion::BlockCodeRegionKind: |
128 | case MemRegion::BlockDataRegionKind: |
129 | case MemRegion::StringRegionKind: |
130 | |
131 | case MemRegion::SymbolicRegionKind: |
132 | case MemRegion::AllocaRegionKind: |
133 | case MemRegion::CompoundLiteralRegionKind: |
134 | case MemRegion::FieldRegionKind: |
135 | case MemRegion::ObjCIvarRegionKind: |
136 | case MemRegion::ObjCStringRegionKind: |
137 | case MemRegion::VarRegionKind: |
138 | case MemRegion::CXXTempObjectRegionKind: |
139 | case MemRegion::CXXBaseObjectRegionKind: |
140 | case MemRegion::CXXDerivedObjectRegionKind: |
141 | return MakeElementRegion(cast<SubRegion>(R), PointeeTy); |
142 | |
143 | case MemRegion::ElementRegionKind: { |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | const ElementRegion *elementR = cast<ElementRegion>(R); |
164 | const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); |
165 | const MemRegion *baseR = rawOff.getRegion(); |
166 | |
167 | |
168 | |
169 | if (!baseR) |
170 | return nullptr; |
171 | |
172 | CharUnits off = rawOff.getOffset(); |
173 | |
174 | if (off.isZero()) { |
175 | |
176 | |
177 | |
178 | if (const auto *TR = dyn_cast<TypedValueRegion>(baseR)) { |
179 | QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); |
180 | QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); |
181 | if (CanonPointeeTy == ObjTy) |
182 | return baseR; |
183 | } |
184 | |
185 | |
186 | return MakeElementRegion(cast<SubRegion>(baseR), PointeeTy); |
187 | } |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | int64_t newIndex = 0; |
197 | const MemRegion *newSuperR = nullptr; |
198 | |
199 | |
200 | if (!PointeeTy->isIncompleteType()) { |
201 | |
202 | CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy); |
203 | if (!pointeeTySize.isZero()) { |
204 | |
205 | |
206 | |
207 | if (off % pointeeTySize == 0) { |
208 | newIndex = off / pointeeTySize; |
209 | newSuperR = baseR; |
210 | } |
211 | } |
212 | } |
213 | |
214 | if (!newSuperR) { |
215 | |
216 | |
217 | newSuperR = MakeElementRegion(cast<SubRegion>(baseR), Ctx.CharTy, |
218 | off.getQuantity()); |
219 | } |
220 | |
221 | return MakeElementRegion(cast<SubRegion>(newSuperR), PointeeTy, newIndex); |
222 | } |
223 | } |
224 | |
225 | llvm_unreachable("unreachable"); |
226 | } |
227 | |
228 | static bool regionMatchesCXXRecordType(SVal V, QualType Ty) { |
229 | const MemRegion *MR = V.getAsRegion(); |
230 | if (!MR) |
231 | return true; |
232 | |
233 | const auto *TVR = dyn_cast<TypedValueRegion>(MR); |
234 | if (!TVR) |
235 | return true; |
236 | |
237 | const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl(); |
238 | if (!RD) |
239 | return true; |
240 | |
241 | const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl(); |
242 | if (!Expected) |
243 | Expected = Ty->getAsCXXRecordDecl(); |
244 | |
245 | return Expected->getCanonicalDecl() == RD->getCanonicalDecl(); |
246 | } |
247 | |
248 | SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { |
249 | |
250 | |
251 | if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType())) |
252 | return UnknownVal(); |
253 | |
254 | |
255 | SVal Result = Derived; |
256 | for (CastExpr::path_const_iterator I = Cast->path_begin(), |
257 | E = Cast->path_end(); |
258 | I != E; ++I) { |
259 | Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual()); |
260 | } |
261 | return Result; |
262 | } |
263 | |
264 | SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { |
265 | |
266 | SVal Result = Derived; |
267 | for (const auto &I : Path) |
268 | Result = evalDerivedToBase(Result, I.Base->getType(), |
269 | I.Base->isVirtual()); |
270 | return Result; |
271 | } |
272 | |
273 | SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, |
274 | bool IsVirtual) { |
275 | const MemRegion *DerivedReg = Derived.getAsRegion(); |
276 | if (!DerivedReg) |
277 | return Derived; |
278 | |
279 | const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl(); |
280 | if (!BaseDecl) |
281 | BaseDecl = BaseType->getAsCXXRecordDecl(); |
282 | (0) . __assert_fail ("BaseDecl && \"not a C++ object?\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/Store.cpp", 282, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(BaseDecl && "not a C++ object?"); |
283 | |
284 | if (const auto *AlreadyDerivedReg = |
285 | dyn_cast<CXXDerivedObjectRegion>(DerivedReg)) { |
286 | if (const auto *SR = |
287 | dyn_cast<SymbolicRegion>(AlreadyDerivedReg->getSuperRegion())) |
288 | if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl) |
289 | return loc::MemRegionVal(SR); |
290 | |
291 | DerivedReg = AlreadyDerivedReg->getSuperRegion(); |
292 | } |
293 | |
294 | const MemRegion *BaseReg = MRMgr.getCXXBaseObjectRegion( |
295 | BaseDecl, cast<SubRegion>(DerivedReg), IsVirtual); |
296 | |
297 | return loc::MemRegionVal(BaseReg); |
298 | } |
299 | |
300 | |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) { |
307 | if (const auto *TVR = dyn_cast<TypedValueRegion>(MR)) |
308 | return TVR->getValueType()->getAsCXXRecordDecl(); |
309 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) |
310 | return SR->getSymbol()->getType()->getPointeeCXXRecordDecl(); |
311 | return nullptr; |
312 | } |
313 | |
314 | SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType, |
315 | bool &Failed) { |
316 | Failed = false; |
317 | |
318 | const MemRegion *MR = Base.getAsRegion(); |
319 | if (!MR) |
320 | return UnknownVal(); |
321 | |
322 | |
323 | TargetType = TargetType->getPointeeType(); |
324 | assert(!TargetType.isNull()); |
325 | const CXXRecordDecl *TargetClass = TargetType->getAsCXXRecordDecl(); |
326 | if (!TargetClass && !TargetType->isVoidType()) |
327 | return UnknownVal(); |
328 | |
329 | |
330 | |
331 | while (const CXXRecordDecl *MRClass = getCXXRecordType(MR)) { |
332 | |
333 | if (MRClass == TargetClass) |
334 | return loc::MemRegionVal(MR); |
335 | |
336 | |
337 | |
338 | |
339 | if (!TargetType->isVoidType() && MRClass->hasDefinition()) { |
340 | |
341 | |
342 | CXXBasePaths Paths(, , |
343 | ); |
344 | if (MRClass->isDerivedFrom(TargetClass, Paths)) |
345 | return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front()); |
346 | } |
347 | |
348 | if (const auto *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) { |
349 | |
350 | MR = BaseR->getSuperRegion(); |
351 | continue; |
352 | } |
353 | |
354 | |
355 | if (TargetType->isVoidType()) |
356 | return loc::MemRegionVal(MR); |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | |
363 | |
364 | |
365 | |
366 | const MemRegion *Uncasted = MR->StripCasts(); |
367 | if (Uncasted == MR) { |
368 | |
369 | |
370 | |
371 | break; |
372 | } |
373 | |
374 | MR = Uncasted; |
375 | } |
376 | |
377 | |
378 | |
379 | |
380 | |
381 | |
382 | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) { |
383 | QualType T = SR->getSymbol()->getType(); |
384 | const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl(); |
385 | if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass)) |
386 | return loc::MemRegionVal( |
387 | MRMgr.getCXXDerivedObjectRegion(TargetClass, SR)); |
388 | return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType)); |
389 | } |
390 | |
391 | |
392 | Failed = isa<TypedValueRegion>(MR); |
393 | return UnknownVal(); |
394 | } |
395 | |
396 | |
397 | |
398 | |
399 | SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, |
400 | QualType castTy) { |
401 | if (castTy.isNull() || V.isUnknownOrUndef()) |
402 | return V; |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | if (castTy->isFloatingType()) { |
410 | SymbolRef Sym = V.getAsSymbol(); |
411 | if (Sym && !Sym->getType()->isFloatingType()) |
412 | return UnknownVal(); |
413 | } |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | if (castTy->isPointerType() && !castTy->isVoidPointerType()) |
424 | if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) |
425 | if (SR->getSymbol()->getType().getCanonicalType() != |
426 | castTy.getCanonicalType()) |
427 | return loc::MemRegionVal(castRegion(SR, castTy)); |
428 | |
429 | return svalBuilder.dispatchCast(V, castTy); |
430 | } |
431 | |
432 | SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { |
433 | if (Base.isUnknownOrUndef()) |
434 | return Base; |
435 | |
436 | Loc BaseL = Base.castAs<Loc>(); |
437 | const SubRegion* BaseR = nullptr; |
438 | |
439 | switch (BaseL.getSubKind()) { |
440 | case loc::MemRegionValKind: |
441 | BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion()); |
442 | break; |
443 | |
444 | case loc::GotoLabelKind: |
445 | |
446 | return UndefinedVal(); |
447 | |
448 | case loc::ConcreteIntKind: |
449 | |
450 | |
451 | |
452 | |
453 | |
454 | |
455 | |
456 | |
457 | |
458 | |
459 | return Base; |
460 | |
461 | default: |
462 | llvm_unreachable("Unhandled Base."); |
463 | } |
464 | |
465 | |
466 | |
467 | if (const auto *ID = dyn_cast<ObjCIvarDecl>(D)) |
468 | return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); |
469 | |
470 | return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); |
471 | } |
472 | |
473 | SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) { |
474 | return getLValueFieldOrIvar(decl, base); |
475 | } |
476 | |
477 | SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, |
478 | SVal Base) { |
479 | |
480 | |
481 | |
482 | |
483 | if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>()) |
484 | return Base; |
485 | |
486 | if (Base.getAs<loc::GotoLabel>()) |
487 | return UnknownVal(); |
488 | |
489 | const SubRegion *BaseRegion = |
490 | Base.castAs<loc::MemRegionVal>().getRegionAs<SubRegion>(); |
491 | |
492 | |
493 | const auto *ElemR = dyn_cast<ElementRegion>(BaseRegion); |
494 | |
495 | |
496 | Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>(); |
497 | |
498 | if (!ElemR) { |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, |
507 | BaseRegion, Ctx)); |
508 | } |
509 | |
510 | SVal BaseIdx = ElemR->getIndex(); |
511 | |
512 | if (!BaseIdx.getAs<nonloc::ConcreteInt>()) |
513 | return UnknownVal(); |
514 | |
515 | const llvm::APSInt &BaseIdxI = |
516 | BaseIdx.castAs<nonloc::ConcreteInt>().getValue(); |
517 | |
518 | |
519 | |
520 | |
521 | if (!Offset.getAs<nonloc::ConcreteInt>()) { |
522 | if (isa<ElementRegion>(BaseRegion->StripCasts())) |
523 | return UnknownVal(); |
524 | |
525 | return loc::MemRegionVal(MRMgr.getElementRegion( |
526 | elementType, Offset, cast<SubRegion>(ElemR->getSuperRegion()), Ctx)); |
527 | } |
528 | |
529 | const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue(); |
530 | assert(BaseIdxI.isSigned()); |
531 | |
532 | |
533 | nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI + |
534 | OffI)); |
535 | |
536 | |
537 | const SubRegion *ArrayR = cast<SubRegion>(ElemR->getSuperRegion()); |
538 | return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, |
539 | Ctx)); |
540 | } |
541 | |
542 | StoreManager::BindingsHandler::~BindingsHandler() = default; |
543 | |
544 | bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr, |
545 | Store store, |
546 | const MemRegion* R, |
547 | SVal val) { |
548 | SymbolRef SymV = val.getAsLocSymbol(); |
549 | if (!SymV || SymV != Sym) |
550 | return true; |
551 | |
552 | if (Binding) { |
553 | First = false; |
554 | return false; |
555 | } |
556 | else |
557 | Binding = R; |
558 | |
559 | return true; |
560 | } |
561 | |