19b3df78bSCharusso //===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- C++ -*-===// 29b3df78bSCharusso // 39b3df78bSCharusso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49b3df78bSCharusso // See https://llvm.org/LICENSE.txt for license information. 59b3df78bSCharusso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69b3df78bSCharusso // 79b3df78bSCharusso //===----------------------------------------------------------------------===// 89b3df78bSCharusso // 99b3df78bSCharusso // This file defines APIs that track and query dynamic extent information. 109b3df78bSCharusso // 119b3df78bSCharusso //===----------------------------------------------------------------------===// 129b3df78bSCharusso 139b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" 149b3df78bSCharusso #include "clang/AST/Expr.h" 159b3df78bSCharusso #include "clang/Basic/LLVM.h" 169b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 179b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 189b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 199b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 209b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 219b3df78bSCharusso 229b3df78bSCharusso REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *, 239b3df78bSCharusso clang::ento::DefinedOrUnknownSVal) 249b3df78bSCharusso 259b3df78bSCharusso namespace clang { 269b3df78bSCharusso namespace ento { 279b3df78bSCharusso 289b3df78bSCharusso DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, 299b3df78bSCharusso const MemRegion *MR, SValBuilder &SVB) { 309b3df78bSCharusso MR = MR->StripCasts(); 319b3df78bSCharusso 329b3df78bSCharusso if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR)) 3312559064Sdingfei if (auto SSize = 3412559064Sdingfei SVB.convertToArrayIndex(*Size).getAs<DefinedOrUnknownSVal>()) 3512559064Sdingfei return *SSize; 369b3df78bSCharusso 379b3df78bSCharusso return MR->getMemRegionManager().getStaticSize(MR, SVB); 389b3df78bSCharusso } 399b3df78bSCharusso 409b3df78bSCharusso DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) { 419b3df78bSCharusso return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(), 429b3df78bSCharusso SVB.getArrayIndexType()); 439b3df78bSCharusso } 449b3df78bSCharusso 4512559064Sdingfei static DefinedOrUnknownSVal getConstantArrayElementCount(SValBuilder &SVB, 4612559064Sdingfei const MemRegion *MR) { 4712559064Sdingfei MR = MR->StripCasts(); 4812559064Sdingfei 4912559064Sdingfei const auto *TVR = MR->getAs<TypedValueRegion>(); 5012559064Sdingfei if (!TVR) 5112559064Sdingfei return UnknownVal(); 5212559064Sdingfei 5312559064Sdingfei if (const ConstantArrayType *CAT = 5412559064Sdingfei SVB.getContext().getAsConstantArrayType(TVR->getValueType())) 5512559064Sdingfei return SVB.makeIntVal(CAT->getSize(), /* isUnsigned = */ false); 5612559064Sdingfei 5712559064Sdingfei return UnknownVal(); 5812559064Sdingfei } 5912559064Sdingfei 6012559064Sdingfei static DefinedOrUnknownSVal 6112559064Sdingfei getDynamicElementCount(ProgramStateRef State, SVal Size, 6212559064Sdingfei DefinedOrUnknownSVal ElementSize) { 6312559064Sdingfei SValBuilder &SVB = State->getStateManager().getSValBuilder(); 6412559064Sdingfei 6512559064Sdingfei auto ElementCount = 6612559064Sdingfei SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType()) 6712559064Sdingfei .getAs<DefinedOrUnknownSVal>(); 6812559064Sdingfei return ElementCount.value_or(UnknownVal()); 6912559064Sdingfei } 7012559064Sdingfei 719b3df78bSCharusso DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, 729b3df78bSCharusso const MemRegion *MR, 739b3df78bSCharusso SValBuilder &SVB, 749b3df78bSCharusso QualType ElementTy) { 752fb3bec9STomasz Kamiński assert(MR != nullptr && "Not-null region expected"); 769b3df78bSCharusso MR = MR->StripCasts(); 779b3df78bSCharusso 7812559064Sdingfei DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB); 7912559064Sdingfei if (ElementSize.isZeroConstant()) 8012559064Sdingfei return getConstantArrayElementCount(SVB, MR); 819b3df78bSCharusso 8212559064Sdingfei return getDynamicElementCount(State, getDynamicExtent(State, MR, SVB), 8312559064Sdingfei ElementSize); 849b3df78bSCharusso } 859b3df78bSCharusso 869b3df78bSCharusso SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) { 8712559064Sdingfei SValBuilder &SVB = State->getStateManager().getSValBuilder(); 889b3df78bSCharusso const MemRegion *MRegion = BufV.getAsRegion(); 899b3df78bSCharusso if (!MRegion) 909b3df78bSCharusso return UnknownVal(); 919b3df78bSCharusso RegionOffset Offset = MRegion->getAsOffset(); 929b3df78bSCharusso if (Offset.hasSymbolicOffset()) 939b3df78bSCharusso return UnknownVal(); 949b3df78bSCharusso const MemRegion *BaseRegion = MRegion->getBaseRegion(); 959b3df78bSCharusso if (!BaseRegion) 969b3df78bSCharusso return UnknownVal(); 979b3df78bSCharusso 9812559064Sdingfei NonLoc OffsetInChars = 9912559064Sdingfei SVB.makeArrayIndex(Offset.getOffset() / SVB.getContext().getCharWidth()); 10012559064Sdingfei DefinedOrUnknownSVal ExtentInBytes = getDynamicExtent(State, BaseRegion, SVB); 1019b3df78bSCharusso 10212559064Sdingfei return SVB.evalBinOp(State, BinaryOperator::Opcode::BO_Sub, ExtentInBytes, 10312559064Sdingfei OffsetInChars, SVB.getArrayIndexType()); 10412559064Sdingfei } 10512559064Sdingfei 10612559064Sdingfei DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State, 10712559064Sdingfei SVal BufV, 10812559064Sdingfei QualType ElementTy) { 10912559064Sdingfei const MemRegion *MR = BufV.getAsRegion(); 11012559064Sdingfei if (!MR) 11112559064Sdingfei return UnknownVal(); 11212559064Sdingfei 11312559064Sdingfei SValBuilder &SVB = State->getStateManager().getSValBuilder(); 11412559064Sdingfei DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB); 11512559064Sdingfei if (ElementSize.isZeroConstant()) 11612559064Sdingfei return getConstantArrayElementCount(SVB, MR); 11712559064Sdingfei 11812559064Sdingfei return getDynamicElementCount(State, getDynamicExtentWithOffset(State, BufV), 11912559064Sdingfei ElementSize); 1209b3df78bSCharusso } 1219b3df78bSCharusso 1229b3df78bSCharusso ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, 123*339282d4SPavel Skripkin DefinedOrUnknownSVal Size) { 1249b3df78bSCharusso MR = MR->StripCasts(); 1259b3df78bSCharusso 1269b3df78bSCharusso if (Size.isUnknown()) 1279b3df78bSCharusso return State; 1289b3df78bSCharusso 1299b3df78bSCharusso return State->set<DynamicExtentMap>(MR->StripCasts(), Size); 1309b3df78bSCharusso } 1319b3df78bSCharusso 1329b3df78bSCharusso } // namespace ento 1339b3df78bSCharusso } // namespace clang 134