13ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===// 23ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// 33ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// The LLVM Compiler Infrastructure 43ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// 53ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// This file is distributed under the University of Illinois Open Source 63ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// License. See LICENSE.TXT for details. 73ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// 83ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu//===----------------------------------------------------------------------===// 93ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// 103ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// This files defines PointerSubChecker, a builtin checker that checks for 113ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// pointer subtractions on two pointers pointing to different memory chunks. 123ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// This check corresponds to CWE-469. 133ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu// 143ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu//===----------------------------------------------------------------------===// 153ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 1623ade507cecd24b03f5e4b5ebaea48eb38060262Argyrios Kyrtzidis#include "ClangSACheckers.h" 17ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 18695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 213ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 223ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xuusing namespace clang; 239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 243ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 253ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xunamespace { 26ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PointerSubChecker 27ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis : public Checker< check::PreStmt<BinaryOperator> > { 286f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith mutable OwningPtr<BuiltinBug> BT; 29983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis 303ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xupublic: 31983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 323ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu}; 333ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 343ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 35983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidisvoid PointerSubChecker::checkPreStmt(const BinaryOperator *B, 36983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis CheckerContext &C) const { 373ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu // When doing pointer subtraction, if the two pointers do not point to the 383ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu // same memory chunk, emit a warning. 392de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() != BO_Sub) 403ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 413ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 428bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 435eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 445eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal LV = state->getSVal(B->getLHS(), LCtx); 455eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal RV = state->getSVal(B->getRHS(), LCtx); 463ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 473ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const MemRegion *LR = LV.getAsRegion(); 483ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const MemRegion *RR = RV.getAsRegion(); 493ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 50adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (!(LR && RR)) 513ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 523ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 53adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu const MemRegion *BaseLR = LR->getBaseRegion(); 54adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu const MemRegion *BaseRR = RR->getBaseRegion(); 55adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu 56adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (BaseLR == BaseRR) 57adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu return; 58adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu 59adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu // Allow arithmetic on different symbolic regions. 60adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) 613ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 623ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 630bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks if (ExplodedNode *N = C.addTransition()) { 643ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu if (!BT) 65983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis BT.reset(new BuiltinBug("Pointer subtraction", 66dfed7a187edf83ab9ab31c3fccd33df7e22ba795Zhongxing Xu "Subtraction of two pointers that do not point to " 67983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis "the same memory chunk may cause incorrect result.")); 68e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *R = new BugReport(*BT, BT->getDescription(), N); 693ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu R->addRange(B->getSourceRange()); 703ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu C.EmitReport(R); 713ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu } 723ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 733ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 74695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerPointerSubChecker(CheckerManager &mgr) { 75983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis mgr.registerChecker<PointerSubChecker>(); 76695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis} 77