xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1fe6060f1SDimitry Andric //===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric //  This file defines APIs that track and query dynamic extent information.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
14fe6060f1SDimitry Andric #include "clang/AST/Expr.h"
15fe6060f1SDimitry Andric #include "clang/Basic/LLVM.h"
16fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
17fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
18fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
19fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
20fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *,
23fe6060f1SDimitry Andric                                clang::ento::DefinedOrUnknownSVal)
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric namespace clang {
26fe6060f1SDimitry Andric namespace ento {
27fe6060f1SDimitry Andric 
getDynamicExtent(ProgramStateRef State,const MemRegion * MR,SValBuilder & SVB)28fe6060f1SDimitry Andric DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
29fe6060f1SDimitry Andric                                       const MemRegion *MR, SValBuilder &SVB) {
30fe6060f1SDimitry Andric   MR = MR->StripCasts();
31fe6060f1SDimitry Andric 
32fe6060f1SDimitry Andric   if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))
33*5f757f3fSDimitry Andric     if (auto SSize =
34*5f757f3fSDimitry Andric             SVB.convertToArrayIndex(*Size).getAs<DefinedOrUnknownSVal>())
35*5f757f3fSDimitry Andric       return *SSize;
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric   return MR->getMemRegionManager().getStaticSize(MR, SVB);
38fe6060f1SDimitry Andric }
39fe6060f1SDimitry Andric 
getElementExtent(QualType Ty,SValBuilder & SVB)40fe6060f1SDimitry Andric DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) {
41fe6060f1SDimitry Andric   return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(),
42fe6060f1SDimitry Andric                         SVB.getArrayIndexType());
43fe6060f1SDimitry Andric }
44fe6060f1SDimitry Andric 
getConstantArrayElementCount(SValBuilder & SVB,const MemRegion * MR)45*5f757f3fSDimitry Andric static DefinedOrUnknownSVal getConstantArrayElementCount(SValBuilder &SVB,
46*5f757f3fSDimitry Andric                                                          const MemRegion *MR) {
47*5f757f3fSDimitry Andric   MR = MR->StripCasts();
48*5f757f3fSDimitry Andric 
49*5f757f3fSDimitry Andric   const auto *TVR = MR->getAs<TypedValueRegion>();
50*5f757f3fSDimitry Andric   if (!TVR)
51*5f757f3fSDimitry Andric     return UnknownVal();
52*5f757f3fSDimitry Andric 
53*5f757f3fSDimitry Andric   if (const ConstantArrayType *CAT =
54*5f757f3fSDimitry Andric           SVB.getContext().getAsConstantArrayType(TVR->getValueType()))
55*5f757f3fSDimitry Andric     return SVB.makeIntVal(CAT->getSize(), /* isUnsigned = */ false);
56*5f757f3fSDimitry Andric 
57*5f757f3fSDimitry Andric   return UnknownVal();
58*5f757f3fSDimitry Andric }
59*5f757f3fSDimitry Andric 
60*5f757f3fSDimitry Andric static DefinedOrUnknownSVal
getDynamicElementCount(ProgramStateRef State,SVal Size,DefinedOrUnknownSVal ElementSize)61*5f757f3fSDimitry Andric getDynamicElementCount(ProgramStateRef State, SVal Size,
62*5f757f3fSDimitry Andric                        DefinedOrUnknownSVal ElementSize) {
63*5f757f3fSDimitry Andric   SValBuilder &SVB = State->getStateManager().getSValBuilder();
64*5f757f3fSDimitry Andric 
65*5f757f3fSDimitry Andric   auto ElementCount =
66*5f757f3fSDimitry Andric       SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType())
67*5f757f3fSDimitry Andric           .getAs<DefinedOrUnknownSVal>();
68*5f757f3fSDimitry Andric   return ElementCount.value_or(UnknownVal());
69*5f757f3fSDimitry Andric }
70*5f757f3fSDimitry Andric 
getDynamicElementCount(ProgramStateRef State,const MemRegion * MR,SValBuilder & SVB,QualType ElementTy)71fe6060f1SDimitry Andric DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
72fe6060f1SDimitry Andric                                             const MemRegion *MR,
73fe6060f1SDimitry Andric                                             SValBuilder &SVB,
74fe6060f1SDimitry Andric                                             QualType ElementTy) {
75bdd1243dSDimitry Andric   assert(MR != nullptr && "Not-null region expected");
76fe6060f1SDimitry Andric   MR = MR->StripCasts();
77fe6060f1SDimitry Andric 
78*5f757f3fSDimitry Andric   DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
79*5f757f3fSDimitry Andric   if (ElementSize.isZeroConstant())
80*5f757f3fSDimitry Andric     return getConstantArrayElementCount(SVB, MR);
81fe6060f1SDimitry Andric 
82*5f757f3fSDimitry Andric   return getDynamicElementCount(State, getDynamicExtent(State, MR, SVB),
83*5f757f3fSDimitry Andric                                 ElementSize);
84fe6060f1SDimitry Andric }
85fe6060f1SDimitry Andric 
getDynamicExtentWithOffset(ProgramStateRef State,SVal BufV)86fe6060f1SDimitry Andric SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) {
87*5f757f3fSDimitry Andric   SValBuilder &SVB = State->getStateManager().getSValBuilder();
88fe6060f1SDimitry Andric   const MemRegion *MRegion = BufV.getAsRegion();
89fe6060f1SDimitry Andric   if (!MRegion)
90fe6060f1SDimitry Andric     return UnknownVal();
91fe6060f1SDimitry Andric   RegionOffset Offset = MRegion->getAsOffset();
92fe6060f1SDimitry Andric   if (Offset.hasSymbolicOffset())
93fe6060f1SDimitry Andric     return UnknownVal();
94fe6060f1SDimitry Andric   const MemRegion *BaseRegion = MRegion->getBaseRegion();
95fe6060f1SDimitry Andric   if (!BaseRegion)
96fe6060f1SDimitry Andric     return UnknownVal();
97fe6060f1SDimitry Andric 
98*5f757f3fSDimitry Andric   NonLoc OffsetInChars =
99*5f757f3fSDimitry Andric       SVB.makeArrayIndex(Offset.getOffset() / SVB.getContext().getCharWidth());
100*5f757f3fSDimitry Andric   DefinedOrUnknownSVal ExtentInBytes = getDynamicExtent(State, BaseRegion, SVB);
101fe6060f1SDimitry Andric 
102*5f757f3fSDimitry Andric   return SVB.evalBinOp(State, BinaryOperator::Opcode::BO_Sub, ExtentInBytes,
103*5f757f3fSDimitry Andric                        OffsetInChars, SVB.getArrayIndexType());
104*5f757f3fSDimitry Andric }
105*5f757f3fSDimitry Andric 
getDynamicElementCountWithOffset(ProgramStateRef State,SVal BufV,QualType ElementTy)106*5f757f3fSDimitry Andric DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State,
107*5f757f3fSDimitry Andric                                                       SVal BufV,
108*5f757f3fSDimitry Andric                                                       QualType ElementTy) {
109*5f757f3fSDimitry Andric   const MemRegion *MR = BufV.getAsRegion();
110*5f757f3fSDimitry Andric   if (!MR)
111*5f757f3fSDimitry Andric     return UnknownVal();
112*5f757f3fSDimitry Andric 
113*5f757f3fSDimitry Andric   SValBuilder &SVB = State->getStateManager().getSValBuilder();
114*5f757f3fSDimitry Andric   DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
115*5f757f3fSDimitry Andric   if (ElementSize.isZeroConstant())
116*5f757f3fSDimitry Andric     return getConstantArrayElementCount(SVB, MR);
117*5f757f3fSDimitry Andric 
118*5f757f3fSDimitry Andric   return getDynamicElementCount(State, getDynamicExtentWithOffset(State, BufV),
119*5f757f3fSDimitry Andric                                 ElementSize);
120fe6060f1SDimitry Andric }
121fe6060f1SDimitry Andric 
setDynamicExtent(ProgramStateRef State,const MemRegion * MR,DefinedOrUnknownSVal Size,SValBuilder & SVB)122fe6060f1SDimitry Andric ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
123fe6060f1SDimitry Andric                                  DefinedOrUnknownSVal Size, SValBuilder &SVB) {
124fe6060f1SDimitry Andric   MR = MR->StripCasts();
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric   if (Size.isUnknown())
127fe6060f1SDimitry Andric     return State;
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric   return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
130fe6060f1SDimitry Andric }
131fe6060f1SDimitry Andric 
132fe6060f1SDimitry Andric } // namespace ento
133fe6060f1SDimitry Andric } // namespace clang
134