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