brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 1f7c282 Raw
147 lines · cpp
1//===- Checker.cpp - C++ Lifetime Safety Checker ----------------*- 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// This file implements the LifetimeChecker, which detects use-after-free10// errors by checking if live origins hold loans that have expired.11//12//===----------------------------------------------------------------------===//13 14#include "clang/Analysis/Analyses/LifetimeSafety/Checker.h"15#include "clang/AST/Expr.h"16#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"17#include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"18#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"19#include "clang/Analysis/Analyses/LifetimeSafety/Loans.h"20#include "clang/Analysis/Analyses/PostOrderCFGView.h"21#include "clang/Analysis/AnalysisDeclContext.h"22#include "clang/Basic/SourceLocation.h"23#include "llvm/ADT/DenseMap.h"24#include "llvm/Support/ErrorHandling.h"25#include "llvm/Support/TimeProfiler.h"26 27namespace clang::lifetimes::internal {28 29static Confidence livenessKindToConfidence(LivenessKind K) {30  switch (K) {31  case LivenessKind::Must:32    return Confidence::Definite;33  case LivenessKind::Maybe:34    return Confidence::Maybe;35  case LivenessKind::Dead:36    return Confidence::None;37  }38  llvm_unreachable("unknown liveness kind");39}40 41namespace {42 43/// Struct to store the complete context for a potential lifetime violation.44struct PendingWarning {45  SourceLocation ExpiryLoc; // Where the loan expired.46  llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> CausingFact;47  Confidence ConfidenceLevel;48};49 50class LifetimeChecker {51private:52  llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap;53  const LoanPropagationAnalysis &LoanPropagation;54  const LiveOriginsAnalysis &LiveOrigins;55  const FactManager &FactMgr;56  LifetimeSafetyReporter *Reporter;57 58public:59  LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,60                  const LiveOriginsAnalysis &LiveOrigins, const FactManager &FM,61                  AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)62      : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), FactMgr(FM),63        Reporter(Reporter) {64    for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())65      for (const Fact *F : FactMgr.getFacts(B))66        if (const auto *EF = F->getAs<ExpireFact>())67          checkExpiry(EF);68    issuePendingWarnings();69  }70 71  /// Checks for use-after-free & use-after-return errors when a loan expires.72  ///73  /// This method examines all live origins at the expiry point and determines74  /// if any of them hold the expiring loan. If so, it creates a pending75  /// warning with the appropriate confidence level based on the liveness76  /// information. The confidence reflects whether the origin is definitely77  /// or maybe live at this point.78  ///79  /// Note: This implementation considers only the confidence of origin80  /// liveness. Future enhancements could also consider the confidence of loan81  /// propagation (e.g., a loan may only be held on some execution paths).82  void checkExpiry(const ExpireFact *EF) {83    LoanID ExpiredLoan = EF->getLoanID();84    LivenessMap Origins = LiveOrigins.getLiveOriginsAt(EF);85    Confidence CurConfidence = Confidence::None;86    // The UseFact or OriginEscapesFact most indicative of a lifetime error,87    // prioritized by earlier source location.88    llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>89        BestCausingFact = nullptr;90 91    for (auto &[OID, LiveInfo] : Origins) {92      LoanSet HeldLoans = LoanPropagation.getLoans(OID, EF);93      if (!HeldLoans.contains(ExpiredLoan))94        continue;95      // Loan is defaulted.96      Confidence NewConfidence = livenessKindToConfidence(LiveInfo.Kind);97      if (CurConfidence < NewConfidence) {98        CurConfidence = NewConfidence;99        BestCausingFact = LiveInfo.CausingFact;100      }101    }102    if (!BestCausingFact)103      return;104    // We have a use-after-free.105    Confidence LastConf = FinalWarningsMap.lookup(ExpiredLoan).ConfidenceLevel;106    if (LastConf >= CurConfidence)107      return;108    FinalWarningsMap[ExpiredLoan] = {/*ExpiryLoc=*/EF->getExpiryLoc(),109                                     /*BestCausingFact=*/BestCausingFact,110                                     /*ConfidenceLevel=*/CurConfidence};111  }112 113  void issuePendingWarnings() {114    if (!Reporter)115      return;116    for (const auto &[LID, Warning] : FinalWarningsMap) {117      const Loan &L = FactMgr.getLoanMgr().getLoan(LID);118      const Expr *IssueExpr = L.IssueExpr;119      llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>120          CausingFact = Warning.CausingFact;121      Confidence Confidence = Warning.ConfidenceLevel;122      SourceLocation ExpiryLoc = Warning.ExpiryLoc;123 124      if (const auto *UF = CausingFact.dyn_cast<const UseFact *>())125        Reporter->reportUseAfterFree(IssueExpr, UF->getUseExpr(), ExpiryLoc,126                                     Confidence);127      else if (const auto *OEF =128                   CausingFact.dyn_cast<const OriginEscapesFact *>())129        Reporter->reportUseAfterReturn(IssueExpr, OEF->getEscapeExpr(),130                                       ExpiryLoc, Confidence);131      else132        llvm_unreachable("Unhandled CausingFact type");133    }134  }135};136} // namespace137 138void runLifetimeChecker(const LoanPropagationAnalysis &LP,139                        const LiveOriginsAnalysis &LO,140                        const FactManager &FactMgr, AnalysisDeclContext &ADC,141                        LifetimeSafetyReporter *Reporter) {142  llvm::TimeTraceScope TimeProfile("LifetimeChecker");143  LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter);144}145 146} // namespace clang::lifetimes::internal147