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/BugReporter/BugType.h" 18 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h" 19 20 using namespace clang; 21 using namespace ento; 22 23 namespace { 24 class PointerSubChecker 25 : public CheckerVisitor<PointerSubChecker> { 26 BuiltinBug *BT; 27 public: 28 PointerSubChecker() : BT(0) {} 29 static void *getTag(); 30 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 31 }; 32 } 33 34 void *PointerSubChecker::getTag() { 35 static int x; 36 return &x; 37 } 38 39 void 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 77 void ento::RegisterPointerSubChecker(ExprEngine &Eng) { 78 Eng.registerCheck(new PointerSubChecker()); 79 } 80