1218887Sdim//=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This files defines PointerArithChecker, a builtin checker that checks for 11218887Sdim// pointer arithmetic on locations other than array elements. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15218887Sdim#include "ClangSACheckers.h" 16252723Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 18218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19219077Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 20218887Sdim 21218887Sdimusing namespace clang; 22218887Sdimusing namespace ento; 23218887Sdim 24218887Sdimnamespace { 25218887Sdimclass PointerArithChecker 26221345Sdim : public Checker< check::PreStmt<BinaryOperator> > { 27235633Sdim mutable OwningPtr<BuiltinBug> BT; 28219077Sdim 29218887Sdimpublic: 30219077Sdim void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 31218887Sdim}; 32218887Sdim} 33218887Sdim 34219077Sdimvoid PointerArithChecker::checkPreStmt(const BinaryOperator *B, 35219077Sdim CheckerContext &C) const { 36218887Sdim if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add) 37218887Sdim return; 38218887Sdim 39235633Sdim ProgramStateRef state = C.getState(); 40235633Sdim const LocationContext *LCtx = C.getLocationContext(); 41235633Sdim SVal LV = state->getSVal(B->getLHS(), LCtx); 42235633Sdim SVal RV = state->getSVal(B->getRHS(), LCtx); 43218887Sdim 44218887Sdim const MemRegion *LR = LV.getAsRegion(); 45218887Sdim 46218887Sdim if (!LR || !RV.isConstant()) 47218887Sdim return; 48218887Sdim 49218887Sdim // If pointer arithmetic is done on variables of non-array type, this often 50218887Sdim // means behavior rely on memory organization, which is dangerous. 51218887Sdim if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) || 52218887Sdim isa<CompoundLiteralRegion>(LR)) { 53218887Sdim 54235633Sdim if (ExplodedNode *N = C.addTransition()) { 55218887Sdim if (!BT) 56219077Sdim BT.reset(new BuiltinBug("Dangerous pointer arithmetic", 57218887Sdim "Pointer arithmetic done on non-array variables " 58218887Sdim "means reliance on memory layout, which is " 59219077Sdim "dangerous.")); 60226890Sdim BugReport *R = new BugReport(*BT, BT->getDescription(), N); 61218887Sdim R->addRange(B->getSourceRange()); 62245431Sdim C.emitReport(R); 63218887Sdim } 64218887Sdim } 65218887Sdim} 66218887Sdim 67218887Sdimvoid ento::registerPointerArithChecker(CheckerManager &mgr) { 68219077Sdim mgr.registerChecker<PointerArithChecker>(); 69218887Sdim} 70