PointerSubChecker.cpp revision 9b663716449b618ba0390b1dbebc54fa8e971124
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 1604291a7c76e16a2dc5433c80c3d13c826bf372dcArgyrios Kyrtzidis#include "InternalChecks.h" 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 193ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 203ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xuusing namespace clang; 219ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 223ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 233ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xunamespace { 24ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass PointerSubChecker 253ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu : public CheckerVisitor<PointerSubChecker> { 263ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu BuiltinBug *BT; 273ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xupublic: 283ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu PointerSubChecker() : BT(0) {} 293ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu static void *getTag(); 303ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 313ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu}; 323ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 333ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 343ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xuvoid *PointerSubChecker::getTag() { 353ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu static int x; 363ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return &x; 373ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 383ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 393ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xuvoid PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C, 403ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const BinaryOperator *B) { 413ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu // When doing pointer subtraction, if the two pointers do not point to the 423ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu // same memory chunk, emit a warning. 432de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() != BO_Sub) 443ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 453ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 463ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const GRState *state = C.getState(); 471397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal LV = state->getSVal(B->getLHS()); 481397663af9dbcc24dbf0e11de43931b3dc08fdbbTed Kremenek SVal RV = state->getSVal(B->getRHS()); 493ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 503ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const MemRegion *LR = LV.getAsRegion(); 513ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu const MemRegion *RR = RV.getAsRegion(); 523ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 53adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (!(LR && RR)) 543ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 553ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 56adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu const MemRegion *BaseLR = LR->getBaseRegion(); 57adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu const MemRegion *BaseRR = RR->getBaseRegion(); 58adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu 59adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (BaseLR == BaseRR) 60adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu return; 61adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu 62adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu // Allow arithmetic on different symbolic regions. 63adca27102ff733c7d42fcbbc2c7e134a7fc026f9Zhongxing Xu if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) 643ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu return; 653ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 66d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode()) { 673ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu if (!BT) 683ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu BT = new BuiltinBug("Pointer subtraction", 69dfed7a187edf83ab9ab31c3fccd33df7e22ba795Zhongxing Xu "Subtraction of two pointers that do not point to " 70dfed7a187edf83ab9ab31c3fccd33df7e22ba795Zhongxing Xu "the same memory chunk may cause incorrect result."); 71d02e232c43b979758810794de24d3f5cde40fe93Benjamin Kramer RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); 723ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu R->addRange(B->getSourceRange()); 733ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu C.EmitReport(R); 743ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu } 753ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 763ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu 779ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekvoid ento::RegisterPointerSubChecker(ExprEngine &Eng) { 783ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu Eng.registerCheck(new PointerSubChecker()); 793ce2dc358ea951c384fa27bcf2ba4a222c2c0511Zhongxing Xu} 80