brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · e5d5e01 Raw
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