DynamicExtent.cpp 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. MR = MR->StripCasts();
  40. DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);
  41. SVal ElementSize = getElementExtent(ElementTy, SVB);
  42. SVal ElementCount =
  43. SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType());
  44. return ElementCount.castAs<DefinedOrUnknownSVal>();
  45. }
  46. SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) {
  47. SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
  48. const MemRegion *MRegion = BufV.getAsRegion();
  49. if (!MRegion)
  50. return UnknownVal();
  51. RegionOffset Offset = MRegion->getAsOffset();
  52. if (Offset.hasSymbolicOffset())
  53. return UnknownVal();
  54. const MemRegion *BaseRegion = MRegion->getBaseRegion();
  55. if (!BaseRegion)
  56. return UnknownVal();
  57. NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
  58. Offset.getOffset() /
  59. MRegion->getMemRegionManager().getContext().getCharWidth());
  60. DefinedOrUnknownSVal ExtentInBytes =
  61. getDynamicExtent(State, BaseRegion, SvalBuilder);
  62. return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
  63. ExtentInBytes, OffsetInBytes,
  64. SvalBuilder.getArrayIndexType());
  65. }
  66. ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
  67. DefinedOrUnknownSVal Size, SValBuilder &SVB) {
  68. MR = MR->StripCasts();
  69. if (Size.isUnknown())
  70. return State;
  71. return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
  72. }
  73. } // namespace ento
  74. } // namespace clang