xref: /llvm-project/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp (revision 339282d49f5310a2837da45c0ccc19da15675554)
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