Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
Line
Count
Source
1
//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This files defines PointerSubChecker, a builtin checker that checks for
10
// pointer subtractions on two pointers pointing to different memory chunks.
11
// This check corresponds to CWE-469.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
16
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17
#include "clang/StaticAnalyzer/Core/Checker.h"
18
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20
21
using namespace clang;
22
using namespace ento;
23
24
namespace {
25
class PointerSubChecker
26
  : public Checker< check::PreStmt<BinaryOperator> > {
27
  mutable std::unique_ptr<BuiltinBug> BT;
28
29
public:
30
  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
31
};
32
}
33
34
void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
35
2.31k
                                     CheckerContext &C) const {
36
2.31k
  // When doing pointer subtraction, if the two pointers do not point to the
37
2.31k
  // same memory chunk, emit a warning.
38
2.31k
  if (B->getOpcode() != BO_Sub)
39
2.22k
    return;
40
94
41
94
  SVal LV = C.getSVal(B->getLHS());
42
94
  SVal RV = C.getSVal(B->getRHS());
43
94
44
94
  const MemRegion *LR = LV.getAsRegion();
45
94
  const MemRegion *RR = RV.getAsRegion();
46
94
47
94
  if (!(LR && 
RR68
))
48
38
    return;
49
56
50
56
  const MemRegion *BaseLR = LR->getBaseRegion();
51
56
  const MemRegion *BaseRR = RR->getBaseRegion();
52
56
53
56
  if (BaseLR == BaseRR)
54
8
    return;
55
48
56
48
  // Allow arithmetic on different symbolic regions.
57
48
  if (isa<SymbolicRegion>(BaseLR) || 
isa<SymbolicRegion>(BaseRR)2
)
58
46
    return;
59
2
60
2
  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
61
2
    if (!BT)
62
2
      BT.reset(
63
2
          new BuiltinBug(this, "Pointer subtraction",
64
2
                         "Subtraction of two pointers that do not point to "
65
2
                         "the same memory chunk may cause incorrect result."));
66
2
    auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
67
2
    R->addRange(B->getSourceRange());
68
2
    C.emitReport(std::move(R));
69
2
  }
70
2
}
71
72
71
void ento::registerPointerSubChecker(CheckerManager &mgr) {
73
71
  mgr.registerChecker<PointerSubChecker>();
74
71
}
75
76
71
bool ento::shouldRegisterPointerSubChecker(const LangOptions &LO) {
77
71
  return true;
78
71
}