PointerArithChecker.cpp revision 04291a7c76e16a2dc5433c80c3d13c826bf372dc
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/BugReporter/BugType.h" 17#include "clang/StaticAnalyzer/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