Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- InvalidatedIteratorChecker.cpp ----------------------------*- 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
// Defines a checker for access of invalidated iterators.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
15
#include "clang/StaticAnalyzer/Core/Checker.h"
16
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
17
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18
19
20
#include "Iterator.h"
21
22
using namespace clang;
23
using namespace ento;
24
using namespace iterator;
25
26
namespace {
27
28
class InvalidatedIteratorChecker
29
  : public Checker<check::PreCall> {
30
31
  std::unique_ptr<BugType> InvalidatedBugType;
32
33
  void verifyAccess(CheckerContext &C, const SVal &Val) const;
34
  void reportBug(const StringRef &Message, const SVal &Val,
35
                 CheckerContext &C, ExplodedNode *ErrNode) const;
36
public:
37
  InvalidatedIteratorChecker();
38
39
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
40
41
};
42
43
} //namespace
44
45
3
InvalidatedIteratorChecker::InvalidatedIteratorChecker() {
46
3
  InvalidatedBugType.reset(
47
3
      new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
48
3
}
49
50
void InvalidatedIteratorChecker::checkPreCall(const CallEvent &Call,
51
177
                                              CheckerContext &C) const {
52
177
  // Check for access of invalidated position
53
177
  const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
54
177
  if (!Func)
55
0
    return;
56
177
57
177
  if (Func->isOverloadedOperator() &&
58
177
      
isAccessOperator(Func->getOverloadedOperator())50
) {
59
48
    // Check for any kind of access of invalidated iterator positions
60
48
    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
61
48
      verifyAccess(C, InstCall->getCXXThisVal());
62
48
    } else {
63
0
      verifyAccess(C, Call.getArgSVal(0));
64
0
    }
65
48
  }
66
177
}
67
68
48
void InvalidatedIteratorChecker::verifyAccess(CheckerContext &C, const SVal &Val) const {
69
48
  auto State = C.getState();
70
48
  const auto *Pos = getIteratorPosition(State, Val);
71
48
  if (Pos && !Pos->isValid()) {
72
20
    auto *N = C.generateErrorNode(State);
73
20
    if (!N) {
74
0
      return;
75
0
    }
76
20
    reportBug("Invalidated iterator accessed.", Val, C, N);
77
20
  }
78
48
}
79
80
void InvalidatedIteratorChecker::reportBug(const StringRef &Message,
81
                                           const SVal &Val, CheckerContext &C,
82
20
                                           ExplodedNode *ErrNode) const {
83
20
  auto R = std::make_unique<PathSensitiveBugReport>(*InvalidatedBugType,
84
20
                                                    Message, ErrNode);
85
20
  R->markInteresting(Val);
86
20
  C.emitReport(std::move(R));
87
20
}
88
89
3
void ento::registerInvalidatedIteratorChecker(CheckerManager &mgr) {
90
3
  mgr.registerChecker<InvalidatedIteratorChecker>();
91
3
}
92
93
3
bool ento::shouldRegisterInvalidatedIteratorChecker(const LangOptions &LO) {
94
3
  return true;
95
3
}