PointerSubChecker.cpp revision 276479
1191665Sbms//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===// 2191665Sbms// 3191665Sbms// The LLVM Compiler Infrastructure 4191665Sbms// 5191665Sbms// This file is distributed under the University of Illinois Open Source 6191665Sbms// License. See LICENSE.TXT for details. 7191665Sbms// 8191665Sbms//===----------------------------------------------------------------------===// 9191665Sbms// 10191665Sbms// This files defines PointerSubChecker, a builtin checker that checks for 11191665Sbms// pointer subtractions on two pointers pointing to different memory chunks. 12191665Sbms// This check corresponds to CWE-469. 13191665Sbms// 14191665Sbms//===----------------------------------------------------------------------===// 15191665Sbms 16191665Sbms#include "ClangSACheckers.h" 17191665Sbms#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 18191665Sbms#include "clang/StaticAnalyzer/Core/Checker.h" 19191665Sbms#include "clang/StaticAnalyzer/Core/CheckerManager.h" 20191665Sbms#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21191665Sbms 22191665Sbmsusing namespace clang; 23191665Sbmsusing namespace ento; 24191665Sbms 25191665Sbmsnamespace { 26191665Sbmsclass PointerSubChecker 27191665Sbms : public Checker< check::PreStmt<BinaryOperator> > { 28191665Sbms mutable std::unique_ptr<BuiltinBug> BT; 29191665Sbms 30191665Sbmspublic: 31191665Sbms void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 32191672Sbms}; 33191665Sbms} 34191665Sbms 35191665Sbmsvoid PointerSubChecker::checkPreStmt(const BinaryOperator *B, 36191665Sbms CheckerContext &C) const { 37191665Sbms // When doing pointer subtraction, if the two pointers do not point to the 38191665Sbms // same memory chunk, emit a warning. 39191665Sbms if (B->getOpcode() != BO_Sub) 40191665Sbms return; 41191665Sbms 42191665Sbms ProgramStateRef state = C.getState(); 43191665Sbms const LocationContext *LCtx = C.getLocationContext(); 44191665Sbms SVal LV = state->getSVal(B->getLHS(), LCtx); 45191665Sbms SVal RV = state->getSVal(B->getRHS(), LCtx); 46191665Sbms 47191665Sbms const MemRegion *LR = LV.getAsRegion(); 48191665Sbms const MemRegion *RR = RV.getAsRegion(); 49191665Sbms 50191665Sbms if (!(LR && RR)) 51191665Sbms return; 52191665Sbms 53191665Sbms const MemRegion *BaseLR = LR->getBaseRegion(); 54191665Sbms const MemRegion *BaseRR = RR->getBaseRegion(); 55191665Sbms 56191665Sbms if (BaseLR == BaseRR) 57191665Sbms return; 58191665Sbms 59191665Sbms // Allow arithmetic on different symbolic regions. 60191665Sbms if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) 61191665Sbms return; 62191665Sbms 63191665Sbms if (ExplodedNode *N = C.addTransition()) { 64191665Sbms if (!BT) 65191665Sbms BT.reset( 66191665Sbms new BuiltinBug(this, "Pointer subtraction", 67191665Sbms "Subtraction of two pointers that do not point to " 68191665Sbms "the same memory chunk may cause incorrect result.")); 69195699Srwatson BugReport *R = new BugReport(*BT, BT->getDescription(), N); 70191665Sbms R->addRange(B->getSourceRange()); 71191665Sbms C.emitReport(R); 72191665Sbms } 73191665Sbms} 74191665Sbms 75191665Sbmsvoid ento::registerPointerSubChecker(CheckerManager &mgr) { 76191665Sbms mgr.registerChecker<PointerSubChecker>(); 77191665Sbms} 78191665Sbms