Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/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
#include "llvm/ADT/StringRef.h"
21
22
using namespace clang;
23
using namespace ento;
24
25
namespace {
26
class PointerSubChecker
27
  : public Checker< check::PreStmt<BinaryOperator> > {
28
  mutable std::unique_ptr<BugType> BT;
29
30
public:
31
  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
32
};
33
}
34
35
void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
36
2.35k
                                     CheckerContext &C) const {
37
  // When doing pointer subtraction, if the two pointers do not point to the
38
  // same memory chunk, emit a warning.
39
2.35k
  if (B->getOpcode() != BO_Sub)
40
2.25k
    return;
41
42
94
  SVal LV = C.getSVal(B->getLHS());
43
94
  SVal RV = C.getSVal(B->getRHS());
44
45
94
  const MemRegion *LR = LV.getAsRegion();
46
94
  const MemRegion *RR = RV.getAsRegion();
47
48
94
  if (!(LR && 
RR68
))
49
38
    return;
50
51
56
  const MemRegion *BaseLR = LR->getBaseRegion();
52
56
  const MemRegion *BaseRR = RR->getBaseRegion();
53
54
56
  if (BaseLR == BaseRR)
55
8
    return;
56
57
  // Allow arithmetic on different symbolic regions.
58
48
  if (isa<SymbolicRegion>(BaseLR) || 
isa<SymbolicRegion>(BaseRR)2
)
59
46
    return;
60
61
2
  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
62
2
    if (!BT)
63
2
      BT.reset(new BugType(this, "Pointer subtraction"));
64
2
    constexpr llvm::StringLiteral Msg =
65
2
        "Subtraction of two pointers that do not point to the same memory "
66
2
        "chunk may cause incorrect result.";
67
2
    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
68
2
    R->addRange(B->getSourceRange());
69
2
    C.emitReport(std::move(R));
70
2
  }
71
2
}
72
73
76
void ento::registerPointerSubChecker(CheckerManager &mgr) {
74
76
  mgr.registerChecker<PointerSubChecker>();
75
76
}
76
77
152
bool ento::shouldRegisterPointerSubChecker(const CheckerManager &mgr) {
78
152
  return true;
79
152
}