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