PointerSubChecker.cpp revision ec8605f1d7ec846dbf51047bfd5c56d32d1ff91c
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===// 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The LLVM Compiler Infrastructure 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details. 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// This files defines PointerSubChecker, a builtin checker that checks for 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// pointer subtractions on two pointers pointing to different memory chunks. 126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// This check corresponds to CWE-469. 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ClangSACheckers.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace clang; 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace ento; 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class PointerSubChecker 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : public Checker< check::PreStmt<BinaryOperator> > { 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mutable llvm::OwningPtr<BuiltinBug> BT; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public: 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}; 336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void PointerSubChecker::checkPreStmt(const BinaryOperator *B, 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext &C) const { 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // When doing pointer subtraction, if the two pointers do not point to the 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // same memory chunk, emit a warning. 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (B->getOpcode() != BO_Sub) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GRState *state = C.getState(); 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SVal LV = state->getSVal(B->getLHS()); 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SVal RV = state->getSVal(B->getRHS()); 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const MemRegion *LR = LV.getAsRegion(); 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const MemRegion *RR = RV.getAsRegion(); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!(LR && RR)) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const MemRegion *BaseLR = LR->getBaseRegion(); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MemRegion *BaseRR = RR->getBaseRegion(); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (BaseLR == BaseRR) 566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Allow arithmetic on different symbolic regions. 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ExplodedNode *N = C.generateNode()) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!BT) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BT.reset(new BuiltinBug("Pointer subtraction", 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "Subtraction of two pointers that do not point to " 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "the same memory chunk may cause incorrect result.")); 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) R->addRange(B->getSourceRange()); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) C.EmitReport(R); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ento::registerPointerSubChecker(CheckerManager &mgr) { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) mgr.registerChecker<PointerSubChecker>(); 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)