xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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 "ClangSACheckers.h"
16  #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17  #include "clang/StaticAnalyzer/Core/Checker.h"
18  #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19  #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20  
21  using namespace clang;
22  using namespace ento;
23  
24  namespace {
25  class PointerArithChecker
26    : public Checker< check::PreStmt<BinaryOperator> > {
27    mutable std::unique_ptr<BuiltinBug> BT;
28  
29  public:
30    void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
31  };
32  }
33  
checkPreStmt(const BinaryOperator * B,CheckerContext & C) const34  void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
35                                         CheckerContext &C) const {
36    if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
37      return;
38  
39    ProgramStateRef state = C.getState();
40    const LocationContext *LCtx = C.getLocationContext();
41    SVal LV = state->getSVal(B->getLHS(), LCtx);
42    SVal RV = state->getSVal(B->getRHS(), LCtx);
43  
44    const MemRegion *LR = LV.getAsRegion();
45  
46    if (!LR || !RV.isConstant())
47      return;
48  
49    // If pointer arithmetic is done on variables of non-array type, this often
50    // means behavior rely on memory organization, which is dangerous.
51    if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
52        isa<CompoundLiteralRegion>(LR)) {
53  
54      if (ExplodedNode *N = C.addTransition()) {
55        if (!BT)
56          BT.reset(
57              new BuiltinBug(this, "Dangerous pointer arithmetic",
58                             "Pointer arithmetic done on non-array variables "
59                             "means reliance on memory layout, which is "
60                             "dangerous."));
61        BugReport *R = new BugReport(*BT, BT->getDescription(), N);
62        R->addRange(B->getSourceRange());
63        C.emitReport(R);
64      }
65    }
66  }
67  
registerPointerArithChecker(CheckerManager & mgr)68  void ento::registerPointerArithChecker(CheckerManager &mgr) {
69    mgr.registerChecker<PointerArithChecker>();
70  }
71