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 21using namespace clang; 22using namespace ento; 23 24namespace { 25class PointerArithChecker 26 : public Checker< check::PreStmt<BinaryOperator> > { 27 mutable std::unique_ptr<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 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.generateNonFatalErrorNode()) { 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 auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N); 62 R->addRange(B->getSourceRange()); 63 C.emitReport(std::move(R)); 64 } 65 } 66} 67 68void ento::registerPointerArithChecker(CheckerManager &mgr) { 69 mgr.registerChecker<PointerArithChecker>(); 70} 71