brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 203743d Raw
139 lines · cpp
1//===-- DebugIteratorModeling.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-exception6//7//===----------------------------------------------------------------------===//8//9// Defines a checker for debugging iterator modeling.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/CallDescription.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"19 20#include "Iterator.h"21 22using namespace clang;23using namespace ento;24using namespace iterator;25 26namespace {27 28class DebugIteratorModeling29  : public Checker<eval::Call> {30 31  const BugType DebugMsgBugType{this, "Checking analyzer assumptions", "debug",32                                /*SuppressOnSink=*/true};33 34  template <typename Getter>35  void analyzerIteratorDataField(const CallExpr *CE, CheckerContext &C,36                                 Getter get, SVal Default) const;37  void analyzerIteratorPosition(const CallExpr *CE, CheckerContext &C) const;38  void analyzerIteratorContainer(const CallExpr *CE, CheckerContext &C) const;39  void analyzerIteratorValidity(const CallExpr *CE, CheckerContext &C) const;40  ExplodedNode *reportDebugMsg(llvm::StringRef Msg, CheckerContext &C) const;41 42  typedef void (DebugIteratorModeling::*FnCheck)(const CallExpr *,43                                                 CheckerContext &) const;44 45  CallDescriptionMap<FnCheck> Callbacks = {46      {{CDM::SimpleFunc, {"clang_analyzer_iterator_position"}, 1},47       &DebugIteratorModeling::analyzerIteratorPosition},48      {{CDM::SimpleFunc, {"clang_analyzer_iterator_container"}, 1},49       &DebugIteratorModeling::analyzerIteratorContainer},50      {{CDM::SimpleFunc, {"clang_analyzer_iterator_validity"}, 1},51       &DebugIteratorModeling::analyzerIteratorValidity},52  };53 54public:55  bool evalCall(const CallEvent &Call, CheckerContext &C) const;56};57 58} // namespace59 60bool DebugIteratorModeling::evalCall(const CallEvent &Call,61                                     CheckerContext &C) const {62  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());63  if (!CE)64    return false;65 66  const FnCheck *Handler = Callbacks.lookup(Call);67  if (!Handler)68    return false;69 70  (this->**Handler)(CE, C);71  return true;72}73 74template <typename Getter>75void DebugIteratorModeling::analyzerIteratorDataField(const CallExpr *CE,76                                                      CheckerContext &C,77                                                      Getter get,78                                                      SVal Default) const {79  if (CE->getNumArgs() == 0) {80    reportDebugMsg("Missing iterator argument", C);81    return;82  }83 84  auto State = C.getState();85  SVal V = C.getSVal(CE->getArg(0));86  const auto *Pos = getIteratorPosition(State, V);87  if (Pos) {88    State = State->BindExpr(CE, C.getLocationContext(), get(Pos));89  } else {90    State = State->BindExpr(CE, C.getLocationContext(), Default);91  }92  C.addTransition(State);93}94 95void DebugIteratorModeling::analyzerIteratorPosition(const CallExpr *CE,96                                                     CheckerContext &C) const {97  auto &BVF = C.getSValBuilder().getBasicValueFactory();98  analyzerIteratorDataField(CE, C, [](const IteratorPosition *P) {99      return nonloc::SymbolVal(P->getOffset());100    }, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));101}102 103void DebugIteratorModeling::analyzerIteratorContainer(const CallExpr *CE,104                                                      CheckerContext &C) const {105  auto &BVF = C.getSValBuilder().getBasicValueFactory();106  analyzerIteratorDataField(CE, C, [](const IteratorPosition *P) {107      return loc::MemRegionVal(P->getContainer());108    }, loc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));109}110 111void DebugIteratorModeling::analyzerIteratorValidity(const CallExpr *CE,112                                                     CheckerContext &C) const {113  auto &BVF = C.getSValBuilder().getBasicValueFactory();114  analyzerIteratorDataField(CE, C, [&BVF](const IteratorPosition *P) {115      return116        nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get((P->isValid()))));117    }, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));118}119 120ExplodedNode *DebugIteratorModeling::reportDebugMsg(llvm::StringRef Msg,121                                                    CheckerContext &C) const {122  ExplodedNode *N = C.generateNonFatalErrorNode();123  if (!N)124    return nullptr;125 126  auto &BR = C.getBugReporter();127  BR.emitReport(128      std::make_unique<PathSensitiveBugReport>(DebugMsgBugType, Msg, N));129  return N;130}131 132void ento::registerDebugIteratorModeling(CheckerManager &mgr) {133  mgr.registerChecker<DebugIteratorModeling>();134}135 136bool ento::shouldRegisterDebugIteratorModeling(const CheckerManager &mgr) {137  return true;138}139