Home | History | Annotate | Download | only in Checkers
      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/Checker.h"
     18 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
     20 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
     21 
     22 using namespace clang;
     23 using namespace ento;
     24 
     25 namespace {
     26 class PointerSubChecker
     27   : public Checker< check::PreStmt<BinaryOperator> > {
     28   mutable llvm::OwningPtr<BuiltinBug> BT;
     29 
     30 public:
     31   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
     32 };
     33 }
     34 
     35 void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
     36                                      CheckerContext &C) const {
     37   // When doing pointer subtraction, if the two pointers do not point to the
     38   // same memory chunk, emit a warning.
     39   if (B->getOpcode() != BO_Sub)
     40     return;
     41 
     42   const ProgramState *state = C.getState();
     43   SVal LV = state->getSVal(B->getLHS());
     44   SVal RV = state->getSVal(B->getRHS());
     45 
     46   const MemRegion *LR = LV.getAsRegion();
     47   const MemRegion *RR = RV.getAsRegion();
     48 
     49   if (!(LR && RR))
     50     return;
     51 
     52   const MemRegion *BaseLR = LR->getBaseRegion();
     53   const MemRegion *BaseRR = RR->getBaseRegion();
     54 
     55   if (BaseLR == BaseRR)
     56     return;
     57 
     58   // Allow arithmetic on different symbolic regions.
     59   if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
     60     return;
     61 
     62   if (ExplodedNode *N = C.generateNode()) {
     63     if (!BT)
     64       BT.reset(new BuiltinBug("Pointer subtraction",
     65                           "Subtraction of two pointers that do not point to "
     66                           "the same memory chunk may cause incorrect result."));
     67     BugReport *R = new BugReport(*BT, BT->getDescription(), N);
     68     R->addRange(B->getSourceRange());
     69     C.EmitReport(R);
     70   }
     71 }
     72 
     73 void ento::registerPointerSubChecker(CheckerManager &mgr) {
     74   mgr.registerChecker<PointerSubChecker>();
     75 }
     76