PointerSubChecker.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This files defines PointerSubChecker, a builtin checker that checks for
  11. // pointer subtractions on two pointers pointing to different memory chunks.
  12. // This check corresponds to CWE-469.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "InternalChecks.h"
  16. #include "clang/StaticAnalyzer/BugReporter/BugType.h"
  17. #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
  18. using namespace clang;
  19. using namespace ento;
  20. namespace {
  21. class PointerSubChecker
  22. : public CheckerVisitor<PointerSubChecker> {
  23. BuiltinBug *BT;
  24. public:
  25. PointerSubChecker() : BT(0) {}
  26. static void *getTag();
  27. void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
  28. };
  29. }
  30. void *PointerSubChecker::getTag() {
  31. static int x;
  32. return &x;
  33. }
  34. void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
  35. const BinaryOperator *B) {
  36. // When doing pointer subtraction, if the two pointers do not point to the
  37. // same memory chunk, emit a warning.
  38. if (B->getOpcode() != BO_Sub)
  39. return;
  40. const GRState *state = C.getState();
  41. SVal LV = state->getSVal(B->getLHS());
  42. SVal RV = state->getSVal(B->getRHS());
  43. const MemRegion *LR = LV.getAsRegion();
  44. const MemRegion *RR = RV.getAsRegion();
  45. if (!(LR && RR))
  46. return;
  47. const MemRegion *BaseLR = LR->getBaseRegion();
  48. const MemRegion *BaseRR = RR->getBaseRegion();
  49. if (BaseLR == BaseRR)
  50. return;
  51. // Allow arithmetic on different symbolic regions.
  52. if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
  53. return;
  54. if (ExplodedNode *N = C.generateNode()) {
  55. if (!BT)
  56. BT = new BuiltinBug("Pointer subtraction",
  57. "Subtraction of two pointers that do not point to "
  58. "the same memory chunk may cause incorrect result.");
  59. RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
  60. R->addRange(B->getSourceRange());
  61. C.EmitReport(R);
  62. }
  63. }
  64. void ento::RegisterPointerSubChecker(ExprEngine &Eng) {
  65. Eng.registerCheck(new PointerSubChecker());
  66. }