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