1 //===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- 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 APIs that track and query dynamic extent information. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" 14 #include "clang/AST/Expr.h" 15 #include "clang/Basic/LLVM.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 21 22 REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *, 23 clang::ento::DefinedOrUnknownSVal) 24 25 namespace clang { 26 namespace ento { 27 28 DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, 29 const MemRegion *MR, SValBuilder &SVB) { 30 MR = MR->StripCasts(); 31 32 if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR)) 33 return *Size; 34 35 return MR->getMemRegionManager().getStaticSize(MR, SVB); 36 } 37 38 DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) { 39 return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(), 40 SVB.getArrayIndexType()); 41 } 42 43 DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, 44 const MemRegion *MR, 45 SValBuilder &SVB, 46 QualType ElementTy) { 47 assert(MR != nullptr && "Not-null region expected"); 48 MR = MR->StripCasts(); 49 50 DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB); 51 SVal ElementSize = getElementExtent(ElementTy, SVB); 52 53 SVal ElementCount = 54 SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType()); 55 56 return ElementCount.castAs<DefinedOrUnknownSVal>(); 57 } 58 59 SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) { 60 SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder(); 61 const MemRegion *MRegion = BufV.getAsRegion(); 62 if (!MRegion) 63 return UnknownVal(); 64 RegionOffset Offset = MRegion->getAsOffset(); 65 if (Offset.hasSymbolicOffset()) 66 return UnknownVal(); 67 const MemRegion *BaseRegion = MRegion->getBaseRegion(); 68 if (!BaseRegion) 69 return UnknownVal(); 70 71 NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex( 72 Offset.getOffset() / 73 MRegion->getMemRegionManager().getContext().getCharWidth()); 74 DefinedOrUnknownSVal ExtentInBytes = 75 getDynamicExtent(State, BaseRegion, SvalBuilder); 76 77 return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub, 78 ExtentInBytes, OffsetInBytes, 79 SvalBuilder.getArrayIndexType()); 80 } 81 82 ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, 83 DefinedOrUnknownSVal Size, SValBuilder &SVB) { 84 MR = MR->StripCasts(); 85 86 if (Size.isUnknown()) 87 return State; 88 89 return State->set<DynamicExtentMap>(MR->StripCasts(), Size); 90 } 91 92 } // namespace ento 93 } // namespace clang 94