1 //===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines APIs that track and query dynamic extent information.
11 //===----------------------------------------------------------------------===//
13 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
14 #include "clang/AST/Expr.h"
15 #include "clang/Basic/LLVM.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
22 REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap
, const clang::ento::MemRegion
*,
23 clang::ento::DefinedOrUnknownSVal
)
28 DefinedOrUnknownSVal
getDynamicExtent(ProgramStateRef State
,
29 const MemRegion
*MR
, SValBuilder
&SVB
) {
30 MR
= MR
->StripCasts();
32 if (const DefinedOrUnknownSVal
*Size
= State
->get
<DynamicExtentMap
>(MR
))
34 SVB
.convertToArrayIndex(*Size
).getAs
<DefinedOrUnknownSVal
>())
37 return MR
->getMemRegionManager().getStaticSize(MR
, SVB
);
40 DefinedOrUnknownSVal
getElementExtent(QualType Ty
, SValBuilder
&SVB
) {
41 return SVB
.makeIntVal(SVB
.getContext().getTypeSizeInChars(Ty
).getQuantity(),
42 SVB
.getArrayIndexType());
45 static DefinedOrUnknownSVal
getConstantArrayElementCount(SValBuilder
&SVB
,
46 const MemRegion
*MR
) {
47 MR
= MR
->StripCasts();
49 const auto *TVR
= MR
->getAs
<TypedValueRegion
>();
53 if (const ConstantArrayType
*CAT
=
54 SVB
.getContext().getAsConstantArrayType(TVR
->getValueType()))
55 return SVB
.makeIntVal(CAT
->getSize(), /* isUnsigned = */ false);
60 static DefinedOrUnknownSVal
61 getDynamicElementCount(ProgramStateRef State
, SVal Size
,
62 DefinedOrUnknownSVal ElementSize
) {
63 SValBuilder
&SVB
= State
->getStateManager().getSValBuilder();
66 SVB
.evalBinOp(State
, BO_Div
, Size
, ElementSize
, SVB
.getArrayIndexType())
67 .getAs
<DefinedOrUnknownSVal
>();
68 return ElementCount
.value_or(UnknownVal());
71 DefinedOrUnknownSVal
getDynamicElementCount(ProgramStateRef State
,
75 assert(MR
!= nullptr && "Not-null region expected");
76 MR
= MR
->StripCasts();
78 DefinedOrUnknownSVal ElementSize
= getElementExtent(ElementTy
, SVB
);
79 if (ElementSize
.isZeroConstant())
80 return getConstantArrayElementCount(SVB
, MR
);
82 return getDynamicElementCount(State
, getDynamicExtent(State
, MR
, SVB
),
86 SVal
getDynamicExtentWithOffset(ProgramStateRef State
, SVal BufV
) {
87 SValBuilder
&SVB
= State
->getStateManager().getSValBuilder();
88 const MemRegion
*MRegion
= BufV
.getAsRegion();
91 RegionOffset Offset
= MRegion
->getAsOffset();
92 if (Offset
.hasSymbolicOffset())
94 const MemRegion
*BaseRegion
= MRegion
->getBaseRegion();
98 NonLoc OffsetInChars
=
99 SVB
.makeArrayIndex(Offset
.getOffset() / SVB
.getContext().getCharWidth());
100 DefinedOrUnknownSVal ExtentInBytes
= getDynamicExtent(State
, BaseRegion
, SVB
);
102 return SVB
.evalBinOp(State
, BinaryOperator::Opcode::BO_Sub
, ExtentInBytes
,
103 OffsetInChars
, SVB
.getArrayIndexType());
106 DefinedOrUnknownSVal
getDynamicElementCountWithOffset(ProgramStateRef State
,
108 QualType ElementTy
) {
109 const MemRegion
*MR
= BufV
.getAsRegion();
113 SValBuilder
&SVB
= State
->getStateManager().getSValBuilder();
114 DefinedOrUnknownSVal ElementSize
= getElementExtent(ElementTy
, SVB
);
115 if (ElementSize
.isZeroConstant())
116 return getConstantArrayElementCount(SVB
, MR
);
118 return getDynamicElementCount(State
, getDynamicExtentWithOffset(State
, BufV
),
122 ProgramStateRef
setDynamicExtent(ProgramStateRef State
, const MemRegion
*MR
,
123 DefinedOrUnknownSVal Size
, SValBuilder
&SVB
) {
124 MR
= MR
->StripCasts();
126 if (Size
.isUnknown())
129 return State
->set
<DynamicExtentMap
>(MR
->StripCasts(), Size
);