140 lines · cpp
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-exception6//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/StaticAnalyzer/Core/PathSensitive/MemRegion.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"20 21REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *,22 clang::ento::DefinedOrUnknownSVal)23 24namespace clang {25namespace ento {26 27DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,28 const MemRegion *MR, SValBuilder &SVB) {29 MR = MR->StripCasts();30 31 if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))32 if (auto SSize =33 SVB.convertToArrayIndex(*Size).getAs<DefinedOrUnknownSVal>())34 return *SSize;35 36 return MR->getMemRegionManager().getStaticSize(MR, SVB);37}38 39DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) {40 return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(),41 SVB.getArrayIndexType());42}43 44static DefinedOrUnknownSVal getConstantArrayElementCount(SValBuilder &SVB,45 const MemRegion *MR) {46 MR = MR->StripCasts();47 48 const auto *TVR = MR->getAs<TypedValueRegion>();49 if (!TVR)50 return UnknownVal();51 52 if (const ConstantArrayType *CAT =53 SVB.getContext().getAsConstantArrayType(TVR->getValueType()))54 return SVB.makeIntVal(CAT->getSize(), /* isUnsigned = */ false);55 56 return UnknownVal();57}58 59static DefinedOrUnknownSVal60getDynamicElementCount(ProgramStateRef State, SVal Size,61 DefinedOrUnknownSVal ElementSize) {62 SValBuilder &SVB = State->getStateManager().getSValBuilder();63 64 auto ElementCount =65 SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType())66 .getAs<DefinedOrUnknownSVal>();67 return ElementCount.value_or(UnknownVal());68}69 70DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,71 const MemRegion *MR,72 SValBuilder &SVB,73 QualType ElementTy) {74 assert(MR != nullptr && "Not-null region expected");75 MR = MR->StripCasts();76 77 DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);78 if (ElementSize.isZeroConstant())79 return getConstantArrayElementCount(SVB, MR);80 81 return getDynamicElementCount(State, getDynamicExtent(State, MR, SVB),82 ElementSize);83}84 85SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) {86 SValBuilder &SVB = State->getStateManager().getSValBuilder();87 const MemRegion *MRegion = BufV.getAsRegion();88 if (!MRegion)89 return UnknownVal();90 RegionOffset Offset = MRegion->getAsOffset();91 if (Offset.hasSymbolicOffset())92 return UnknownVal();93 const MemRegion *BaseRegion = MRegion->getBaseRegion();94 if (!BaseRegion)95 return UnknownVal();96 97 NonLoc OffsetInChars =98 SVB.makeArrayIndex(Offset.getOffset() / SVB.getContext().getCharWidth());99 DefinedOrUnknownSVal ExtentInBytes = getDynamicExtent(State, BaseRegion, SVB);100 101 return SVB.evalBinOp(State, BinaryOperator::Opcode::BO_Sub, ExtentInBytes,102 OffsetInChars, SVB.getArrayIndexType());103}104 105DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State,106 SVal BufV,107 QualType ElementTy) {108 const MemRegion *MR = BufV.getAsRegion();109 if (!MR)110 return UnknownVal();111 112 SValBuilder &SVB = State->getStateManager().getSValBuilder();113 DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);114 if (ElementSize.isZeroConstant())115 return getConstantArrayElementCount(SVB, MR);116 117 return getDynamicElementCount(State, getDynamicExtentWithOffset(State, BufV),118 ElementSize);119}120 121ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,122 DefinedOrUnknownSVal Size) {123 MR = MR->StripCasts();124 125 if (Size.isUnknown())126 return State;127 128 return State->set<DynamicExtentMap>(MR->StripCasts(), Size);129}130 131void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper) {132 for (const auto &I : State->get<DynamicExtentMap>())133 if (SymbolRef Sym = I.second.getAsSymbol())134 if (SymReaper.isLiveRegion(I.first))135 SymReaper.markLive(Sym);136}137 138} // namespace ento139} // namespace clang140