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