DynamicExtent.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //===- DynamicExtent.cpp - Dynamic extent 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 extent information.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
  13. #include "clang/AST/Expr.h"
  14. #include "clang/Basic/LLVM.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
  18. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  20. REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *,
  21. clang::ento::DefinedOrUnknownSVal)
  22. namespace clang {
  23. namespace ento {
  24. DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
  25. const MemRegion *MR, SValBuilder &SVB) {
  26. MR = MR->StripCasts();
  27. if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))
  28. return *Size;
  29. return MR->getMemRegionManager().getStaticSize(MR, SVB);
  30. }
  31. DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) {
  32. return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(),
  33. SVB.getArrayIndexType());
  34. }
  35. DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
  36. const MemRegion *MR,
  37. SValBuilder &SVB,
  38. QualType ElementTy) {
  39. assert(MR != nullptr && "Not-null region expected");
  40. MR = MR->StripCasts();
  41. DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);
  42. SVal ElementSize = getElementExtent(ElementTy, SVB);
  43. SVal ElementCount =
  44. SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType());
  45. return ElementCount.castAs<DefinedOrUnknownSVal>();
  46. }
  47. SVal getDynamicExtentWithOffset(ProgramStateRef State, 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. NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
  59. Offset.getOffset() /
  60. MRegion->getMemRegionManager().getContext().getCharWidth());
  61. DefinedOrUnknownSVal ExtentInBytes =
  62. getDynamicExtent(State, BaseRegion, SvalBuilder);
  63. return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
  64. ExtentInBytes, OffsetInBytes,
  65. SvalBuilder.getArrayIndexType());
  66. }
  67. ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
  68. DefinedOrUnknownSVal Size, SValBuilder &SVB) {
  69. MR = MR->StripCasts();
  70. if (Size.isUnknown())
  71. return State;
  72. return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
  73. }
  74. } // namespace ento
  75. } // namespace clang