Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
213799 views
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, check::PreStmt<UnaryOperator>,
30
check::PreStmt<BinaryOperator>,
31
check::PreStmt<ArraySubscriptExpr>,
32
check::PreStmt<MemberExpr>> {
33
34
const BugType InvalidatedBugType{this, "Iterator invalidated",
35
"Misuse of STL APIs"};
36
37
void verifyAccess(CheckerContext &C, SVal Val) const;
38
void reportBug(StringRef Message, SVal Val, CheckerContext &C,
39
ExplodedNode *ErrNode) const;
40
41
public:
42
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
43
void checkPreStmt(const UnaryOperator *UO, CheckerContext &C) const;
44
void checkPreStmt(const BinaryOperator *BO, CheckerContext &C) const;
45
void checkPreStmt(const ArraySubscriptExpr *ASE, CheckerContext &C) const;
46
void checkPreStmt(const MemberExpr *ME, CheckerContext &C) const;
47
48
};
49
50
} // namespace
51
52
void InvalidatedIteratorChecker::checkPreCall(const CallEvent &Call,
53
CheckerContext &C) const {
54
// Check for access of invalidated position
55
const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
56
if (!Func)
57
return;
58
59
if (Func->isOverloadedOperator() &&
60
isAccessOperator(Func->getOverloadedOperator())) {
61
// Check for any kind of access of invalidated iterator positions
62
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
63
verifyAccess(C, InstCall->getCXXThisVal());
64
} else {
65
verifyAccess(C, Call.getArgSVal(0));
66
}
67
}
68
}
69
70
void InvalidatedIteratorChecker::checkPreStmt(const UnaryOperator *UO,
71
CheckerContext &C) const {
72
if (isa<CXXThisExpr>(UO->getSubExpr()))
73
return;
74
75
ProgramStateRef State = C.getState();
76
UnaryOperatorKind OK = UO->getOpcode();
77
SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());
78
79
if (isAccessOperator(OK)) {
80
verifyAccess(C, SubVal);
81
}
82
}
83
84
void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
85
CheckerContext &C) const {
86
ProgramStateRef State = C.getState();
87
BinaryOperatorKind OK = BO->getOpcode();
88
SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
89
90
if (isAccessOperator(OK)) {
91
verifyAccess(C, LVal);
92
}
93
}
94
95
void InvalidatedIteratorChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
96
CheckerContext &C) const {
97
ProgramStateRef State = C.getState();
98
SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());
99
verifyAccess(C, LVal);
100
}
101
102
void InvalidatedIteratorChecker::checkPreStmt(const MemberExpr *ME,
103
CheckerContext &C) const {
104
if (!ME->isArrow() || ME->isImplicitAccess())
105
return;
106
107
ProgramStateRef State = C.getState();
108
SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());
109
verifyAccess(C, BaseVal);
110
}
111
112
void InvalidatedIteratorChecker::verifyAccess(CheckerContext &C,
113
SVal Val) const {
114
auto State = C.getState();
115
const auto *Pos = getIteratorPosition(State, Val);
116
if (Pos && !Pos->isValid()) {
117
auto *N = C.generateErrorNode(State);
118
if (!N) {
119
return;
120
}
121
reportBug("Invalidated iterator accessed.", Val, C, N);
122
}
123
}
124
125
void InvalidatedIteratorChecker::reportBug(StringRef Message, SVal Val,
126
CheckerContext &C,
127
ExplodedNode *ErrNode) const {
128
auto R = std::make_unique<PathSensitiveBugReport>(InvalidatedBugType, Message,
129
ErrNode);
130
R->markInteresting(Val);
131
C.emitReport(std::move(R));
132
}
133
134
void ento::registerInvalidatedIteratorChecker(CheckerManager &mgr) {
135
mgr.registerChecker<InvalidatedIteratorChecker>();
136
}
137
138
bool ento::shouldRegisterInvalidatedIteratorChecker(const CheckerManager &mgr) {
139
return true;
140
}
141
142