PointerSubChecker.cpp revision 23ade507cecd24b03f5e4b5ebaea48eb38060262
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
16#include "ClangSACheckers.h"
17#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
19
20using namespace clang;
21using namespace ento;
22
23namespace {
24class PointerSubChecker
25  : public CheckerVisitor<PointerSubChecker> {
26  BuiltinBug *BT;
27public:
28  PointerSubChecker() : BT(0) {}
29  static void *getTag();
30  void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
31};
32}
33
34void *PointerSubChecker::getTag() {
35  static int x;
36  return &x;
37}
38
39void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
40                                               const BinaryOperator *B) {
41  // When doing pointer subtraction, if the two pointers do not point to the
42  // same memory chunk, emit a warning.
43  if (B->getOpcode() != BO_Sub)
44    return;
45
46  const GRState *state = C.getState();
47  SVal LV = state->getSVal(B->getLHS());
48  SVal RV = state->getSVal(B->getRHS());
49
50  const MemRegion *LR = LV.getAsRegion();
51  const MemRegion *RR = RV.getAsRegion();
52
53  if (!(LR && RR))
54    return;
55
56  const MemRegion *BaseLR = LR->getBaseRegion();
57  const MemRegion *BaseRR = RR->getBaseRegion();
58
59  if (BaseLR == BaseRR)
60    return;
61
62  // Allow arithmetic on different symbolic regions.
63  if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
64    return;
65
66  if (ExplodedNode *N = C.generateNode()) {
67    if (!BT)
68      BT = new BuiltinBug("Pointer subtraction",
69                          "Subtraction of two pointers that do not point to "
70                          "the same memory chunk may cause incorrect result.");
71    RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
72    R->addRange(B->getSourceRange());
73    C.EmitReport(R);
74  }
75}
76
77void ento::registerPointerSubChecker(ExprEngine &Eng) {
78  Eng.registerCheck(new PointerSubChecker());
79}
80