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 OwningPtr<BuiltinBug> BT; 28 29 public: 30 void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 31 }; 32 } 33 34 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(new BuiltinBug("Dangerous pointer arithmetic", 57 "Pointer arithmetic done on non-array variables " 58 "means reliance on memory layout, which is " 59 "dangerous.")); 60 BugReport *R = new BugReport(*BT, BT->getDescription(), N); 61 R->addRange(B->getSourceRange()); 62 C.emitReport(R); 63 } 64 } 65 } 66 67 void ento::registerPointerArithChecker(CheckerManager &mgr) { 68 mgr.registerChecker<PointerArithChecker>(); 69 } 70