PointerSubChecker.cpp revision 9b663716449b618ba0390b1dbebc54fa8e971124
1//=== PointerSubChecker.cpp - Pointer subtraction 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 PointerSubChecker, a builtin checker that checks for 11// pointer subtractions on two pointers pointing to different memory chunks. 12// This check corresponds to CWE-469. 13// 14//===----------------------------------------------------------------------===// 15 16#include "InternalChecks.h" 17#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 18#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 19 20using namespace clang; 21using namespace ento; 22 23namespace { 24class PointerSubChecker 25 : public CheckerVisitor<PointerSubChecker> { 26 BuiltinBug *BT; 27public: 28 PointerSubChecker() : BT(0) {} 29 static void *getTag(); 30 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 31}; 32} 33 34void *PointerSubChecker::getTag() { 35 static int x; 36 return &x; 37} 38 39void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C, 40 const BinaryOperator *B) { 41 // When doing pointer subtraction, if the two pointers do not point to the 42 // same memory chunk, emit a warning. 43 if (B->getOpcode() != BO_Sub) 44 return; 45 46 const GRState *state = C.getState(); 47 SVal LV = state->getSVal(B->getLHS()); 48 SVal RV = state->getSVal(B->getRHS()); 49 50 const MemRegion *LR = LV.getAsRegion(); 51 const MemRegion *RR = RV.getAsRegion(); 52 53 if (!(LR && RR)) 54 return; 55 56 const MemRegion *BaseLR = LR->getBaseRegion(); 57 const MemRegion *BaseRR = RR->getBaseRegion(); 58 59 if (BaseLR == BaseRR) 60 return; 61 62 // Allow arithmetic on different symbolic regions. 63 if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) 64 return; 65 66 if (ExplodedNode *N = C.generateNode()) { 67 if (!BT) 68 BT = new BuiltinBug("Pointer subtraction", 69 "Subtraction of two pointers that do not point to " 70 "the same memory chunk may cause incorrect result."); 71 RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); 72 R->addRange(B->getSourceRange()); 73 C.EmitReport(R); 74 } 75} 76 77void ento::RegisterPointerSubChecker(ExprEngine &Eng) { 78 Eng.registerCheck(new PointerSubChecker()); 79} 80