1//===- DynamicSize.cpp - Dynamic size 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines APIs that track and query dynamic size information.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.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"
21
22namespace clang {
23namespace ento {
24
25DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
26                                    SValBuilder &SVB) {
27  return MR->getMemRegionManager().getStaticSize(MR, SVB);
28}
29
30DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
31                                            const MemRegion *MR,
32                                            SValBuilder &SVB,
33                                            QualType ElementTy) {
34  MemRegionManager &MemMgr = MR->getMemRegionManager();
35  ASTContext &Ctx = MemMgr.getContext();
36
37  DefinedOrUnknownSVal Size = getDynamicSize(State, MR, SVB);
38  SVal ElementSizeV = SVB.makeIntVal(
39      Ctx.getTypeSizeInChars(ElementTy).getQuantity(), SVB.getArrayIndexType());
40
41  SVal DivisionV =
42      SVB.evalBinOp(State, BO_Div, Size, ElementSizeV, SVB.getArrayIndexType());
43
44  return DivisionV.castAs<DefinedOrUnknownSVal>();
45}
46
47SVal getDynamicSizeWithOffset(ProgramStateRef State, const SVal &BufV) {
48  SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
49  const MemRegion *MRegion = BufV.getAsRegion();
50  if (!MRegion)
51    return UnknownVal();
52  RegionOffset Offset = MRegion->getAsOffset();
53  if (Offset.hasSymbolicOffset())
54    return UnknownVal();
55  const MemRegion *BaseRegion = MRegion->getBaseRegion();
56  if (!BaseRegion)
57    return UnknownVal();
58
59  NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
60      Offset.getOffset() /
61      MRegion->getMemRegionManager().getContext().getCharWidth());
62  DefinedOrUnknownSVal ExtentInBytes =
63      getDynamicSize(State, BaseRegion, SvalBuilder);
64
65  return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
66                               ExtentInBytes, OffsetInBytes,
67                               SvalBuilder.getArrayIndexType());
68}
69
70} // namespace ento
71} // namespace clang
72