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