clang  14.0.0git
InvalidatedIteratorChecker.cpp
Go to the documentation of this file.
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 
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  std::unique_ptr<BugType> InvalidatedBugType;
35 
36  void verifyAccess(CheckerContext &C, const SVal &Val) const;
37  void reportBug(const StringRef &Message, const SVal &Val,
38  CheckerContext &C, ExplodedNode *ErrNode) const;
39 public:
40  InvalidatedIteratorChecker();
41 
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 InvalidatedIteratorChecker::InvalidatedIteratorChecker() {
53  InvalidatedBugType.reset(
54  new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
55 }
56 
57 void InvalidatedIteratorChecker::checkPreCall(const CallEvent &Call,
58  CheckerContext &C) const {
59  // Check for access of invalidated position
60  const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
61  if (!Func)
62  return;
63 
64  if (Func->isOverloadedOperator() &&
65  isAccessOperator(Func->getOverloadedOperator())) {
66  // Check for any kind of access of invalidated iterator positions
67  if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
68  verifyAccess(C, InstCall->getCXXThisVal());
69  } else {
70  verifyAccess(C, Call.getArgSVal(0));
71  }
72  }
73 }
74 
75 void InvalidatedIteratorChecker::checkPreStmt(const UnaryOperator *UO,
76  CheckerContext &C) const {
77  if (isa<CXXThisExpr>(UO->getSubExpr()))
78  return;
79 
80  ProgramStateRef State = C.getState();
81  UnaryOperatorKind OK = UO->getOpcode();
82  SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());
83 
84  if (isAccessOperator(OK)) {
85  verifyAccess(C, SubVal);
86  }
87 }
88 
89 void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
90  CheckerContext &C) const {
91  ProgramStateRef State = C.getState();
92  BinaryOperatorKind OK = BO->getOpcode();
93  SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
94 
95  if (isAccessOperator(OK)) {
96  verifyAccess(C, LVal);
97  }
98 }
99 
100 void InvalidatedIteratorChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
101  CheckerContext &C) const {
102  ProgramStateRef State = C.getState();
103  SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());
104  verifyAccess(C, LVal);
105 }
106 
107 void InvalidatedIteratorChecker::checkPreStmt(const MemberExpr *ME,
108  CheckerContext &C) const {
109  if (!ME->isArrow() || ME->isImplicitAccess())
110  return;
111 
112  ProgramStateRef State = C.getState();
113  SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());
114  verifyAccess(C, BaseVal);
115 }
116 
117 void InvalidatedIteratorChecker::verifyAccess(CheckerContext &C, const SVal &Val) const {
118  auto State = C.getState();
119  const auto *Pos = getIteratorPosition(State, Val);
120  if (Pos && !Pos->isValid()) {
121  auto *N = C.generateErrorNode(State);
122  if (!N) {
123  return;
124  }
125  reportBug("Invalidated iterator accessed.", Val, C, N);
126  }
127 }
128 
129 void InvalidatedIteratorChecker::reportBug(const StringRef &Message,
130  const SVal &Val, CheckerContext &C,
131  ExplodedNode *ErrNode) const {
132  auto R = std::make_unique<PathSensitiveBugReport>(*InvalidatedBugType,
133  Message, ErrNode);
134  R->markInteresting(Val);
135  C.emitReport(std::move(R));
136 }
137 
138 void ento::registerInvalidatedIteratorChecker(CheckerManager &mgr) {
139  mgr.registerChecker<InvalidatedIteratorChecker>();
140 }
141 
142 bool ento::shouldRegisterInvalidatedIteratorChecker(const CheckerManager &mgr) {
143  return true;
144 }
clang::ento::ProgramStateRef
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Definition: ProgramState_Fwd.h:37
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::MemberExpr::isImplicitAccess
bool isImplicitAccess() const
Determine whether the base of this explicit is implicit.
Definition: Expr.h:3360
clang::UnaryOperator
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2157
clang::index::SymbolRole::Call
@ Call
clang::BinaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:3847
CallEvent.h
BuiltinCheckerRegistration.h
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3803
clang::MemberExpr::isArrow
bool isArrow() const
Definition: Expr.h:3346
clang::ento::iterator::getIteratorPosition
const IteratorPosition * getIteratorPosition(ProgramStateRef State, const SVal &Val)
Definition: Iterator.cpp:184
clang::ArraySubscriptExpr::getLHS
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
Definition: Expr.h:2668
clang::MemberExpr::getBase
Expr * getBase() const
Definition: Expr.h:3239
BugType.h
clang::BinaryOperator::getLHS
Expr * getLHS() const
Definition: Expr.h:3852
Iterator.h
clang::ArraySubscriptExpr
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2639
State
LineState State
Definition: UnwrappedLineFormatter.cpp:987
clang::UnaryOperatorKind
UnaryOperatorKind
Definition: OperationKinds.h:30
clang::BinaryOperatorKind
BinaryOperatorKind
Definition: OperationKinds.h:25
CheckerContext.h
Checker.h
clang::UnaryOperator::getSubExpr
Expr * getSubExpr() const
Definition: Expr.h:2204
clang
Definition: CalledOnceCheck.h:17
clang::UnaryOperator::getOpcode
Opcode getOpcode() const
Definition: Expr.h:2199
clang::ento::iterator::isAccessOperator
bool isAccessOperator(OverloadedOperatorKind OK)
Definition: Iterator.cpp:126
clang::MemberExpr
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3162