Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
213799 views
//===-- InvalidatedIteratorChecker.cpp ----------------------------*- C++ -*--//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines a checker for access of invalidated iterators.9//10//===----------------------------------------------------------------------===//1112#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"13#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"14#include "clang/StaticAnalyzer/Core/Checker.h"15#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"171819#include "Iterator.h"2021using namespace clang;22using namespace ento;23using namespace iterator;2425namespace {2627class InvalidatedIteratorChecker28: public Checker<check::PreCall, check::PreStmt<UnaryOperator>,29check::PreStmt<BinaryOperator>,30check::PreStmt<ArraySubscriptExpr>,31check::PreStmt<MemberExpr>> {3233const BugType InvalidatedBugType{this, "Iterator invalidated",34"Misuse of STL APIs"};3536void verifyAccess(CheckerContext &C, SVal Val) const;37void reportBug(StringRef Message, SVal Val, CheckerContext &C,38ExplodedNode *ErrNode) const;3940public:41void checkPreCall(const CallEvent &Call, CheckerContext &C) const;42void checkPreStmt(const UnaryOperator *UO, CheckerContext &C) const;43void checkPreStmt(const BinaryOperator *BO, CheckerContext &C) const;44void checkPreStmt(const ArraySubscriptExpr *ASE, CheckerContext &C) const;45void checkPreStmt(const MemberExpr *ME, CheckerContext &C) const;4647};4849} // namespace5051void InvalidatedIteratorChecker::checkPreCall(const CallEvent &Call,52CheckerContext &C) const {53// Check for access of invalidated position54const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());55if (!Func)56return;5758if (Func->isOverloadedOperator() &&59isAccessOperator(Func->getOverloadedOperator())) {60// Check for any kind of access of invalidated iterator positions61if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {62verifyAccess(C, InstCall->getCXXThisVal());63} else {64verifyAccess(C, Call.getArgSVal(0));65}66}67}6869void InvalidatedIteratorChecker::checkPreStmt(const UnaryOperator *UO,70CheckerContext &C) const {71if (isa<CXXThisExpr>(UO->getSubExpr()))72return;7374ProgramStateRef State = C.getState();75UnaryOperatorKind OK = UO->getOpcode();76SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());7778if (isAccessOperator(OK)) {79verifyAccess(C, SubVal);80}81}8283void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,84CheckerContext &C) const {85ProgramStateRef State = C.getState();86BinaryOperatorKind OK = BO->getOpcode();87SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());8889if (isAccessOperator(OK)) {90verifyAccess(C, LVal);91}92}9394void InvalidatedIteratorChecker::checkPreStmt(const ArraySubscriptExpr *ASE,95CheckerContext &C) const {96ProgramStateRef State = C.getState();97SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());98verifyAccess(C, LVal);99}100101void InvalidatedIteratorChecker::checkPreStmt(const MemberExpr *ME,102CheckerContext &C) const {103if (!ME->isArrow() || ME->isImplicitAccess())104return;105106ProgramStateRef State = C.getState();107SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());108verifyAccess(C, BaseVal);109}110111void InvalidatedIteratorChecker::verifyAccess(CheckerContext &C,112SVal Val) const {113auto State = C.getState();114const auto *Pos = getIteratorPosition(State, Val);115if (Pos && !Pos->isValid()) {116auto *N = C.generateErrorNode(State);117if (!N) {118return;119}120reportBug("Invalidated iterator accessed.", Val, C, N);121}122}123124void InvalidatedIteratorChecker::reportBug(StringRef Message, SVal Val,125CheckerContext &C,126ExplodedNode *ErrNode) const {127auto R = std::make_unique<PathSensitiveBugReport>(InvalidatedBugType, Message,128ErrNode);129R->markInteresting(Val);130C.emitReport(std::move(R));131}132133void ento::registerInvalidatedIteratorChecker(CheckerManager &mgr) {134mgr.registerChecker<InvalidatedIteratorChecker>();135}136137bool ento::shouldRegisterInvalidatedIteratorChecker(const CheckerManager &mgr) {138return true;139}140141142