PointerArithChecker.cpp revision 9b663716449b618ba0390b1dbebc54fa8e971124
1//=== PointerArithChecker.cpp - Pointer arithmetic 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 PointerArithChecker, a builtin checker that checks for
11// pointer arithmetic on locations other than array elements.
12//
13//===----------------------------------------------------------------------===//
14
15#include "InternalChecks.h"
16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
18
19using namespace clang;
20using namespace ento;
21
22namespace {
23class PointerArithChecker
24  : public CheckerVisitor<PointerArithChecker> {
25  BuiltinBug *BT;
26public:
27  PointerArithChecker() : BT(0) {}
28  static void *getTag();
29  void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
30};
31}
32
33void *PointerArithChecker::getTag() {
34  static int x;
35  return &x;
36}
37
38void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
39                                                 const BinaryOperator *B) {
40  if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
41    return;
42
43  const GRState *state = C.getState();
44  SVal LV = state->getSVal(B->getLHS());
45  SVal RV = state->getSVal(B->getRHS());
46
47  const MemRegion *LR = LV.getAsRegion();
48
49  if (!LR || !RV.isConstant())
50    return;
51
52  // If pointer arithmetic is done on variables of non-array type, this often
53  // means behavior rely on memory organization, which is dangerous.
54  if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
55      isa<CompoundLiteralRegion>(LR)) {
56
57    if (ExplodedNode *N = C.generateNode()) {
58      if (!BT)
59        BT = new BuiltinBug("Dangerous pointer arithmetic",
60                            "Pointer arithmetic done on non-array variables "
61                            "means reliance on memory layout, which is "
62                            "dangerous.");
63      RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
64      R->addRange(B->getSourceRange());
65      C.EmitReport(R);
66    }
67  }
68}
69
70void ento::RegisterPointerArithChecker(ExprEngine &Eng) {
71  Eng.registerCheck(new PointerArithChecker());
72}
73