clang 22.0.0git
Checker.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the LifetimeChecker, which detects use-after-free
10// errors by checking if live origins hold loans that have expired.
11//
12//===----------------------------------------------------------------------===//
13
15#include "clang/AST/Expr.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/TimeProfiler.h"
26
28
30 switch (K) {
34 return Confidence::Maybe;
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 const Expr *UseExpr; // Where the origin holding this loan was used.
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 errors when a loan expires.
72 ///
73 /// This method examines all live origins at the expiry point and determines
74 /// if any of them hold the expiring loan. If so, it creates a pending
75 /// warning with the appropriate confidence level based on the liveness
76 /// information. The confidence reflects whether the origin is definitely
77 /// or maybe live at this point.
78 ///
79 /// Note: This implementation considers only the confidence of origin
80 /// liveness. Future enhancements could also consider the confidence of loan
81 /// 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 const UseFact *BadUse = nullptr;
87 for (auto &[OID, LiveInfo] : Origins) {
88 LoanSet HeldLoans = LoanPropagation.getLoans(OID, EF);
89 if (!HeldLoans.contains(ExpiredLoan))
90 continue;
91 // Loan is defaulted.
92 Confidence NewConfidence = livenessKindToConfidence(LiveInfo.Kind);
93 if (CurConfidence < NewConfidence) {
94 CurConfidence = NewConfidence;
95 BadUse = LiveInfo.CausingUseFact;
96 }
97 }
98 if (!BadUse)
99 return;
100 // We have a use-after-free.
101 Confidence LastConf = FinalWarningsMap.lookup(ExpiredLoan).ConfidenceLevel;
102 if (LastConf >= CurConfidence)
103 return;
104 FinalWarningsMap[ExpiredLoan] = {/*ExpiryLoc=*/EF->getExpiryLoc(),
105 /*UseExpr=*/BadUse->getUseExpr(),
106 /*ConfidenceLevel=*/CurConfidence};
107 }
108
109 void issuePendingWarnings() {
110 if (!Reporter)
111 return;
112 for (const auto &[LID, Warning] : FinalWarningsMap) {
113 const Loan &L = FactMgr.getLoanMgr().getLoan(LID);
114 const Expr *IssueExpr = L.IssueExpr;
115 Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr,
116 Warning.ExpiryLoc, Warning.ConfidenceLevel);
117 }
118 }
119};
120} // namespace
121
123 const LiveOriginsAnalysis &LO,
124 const FactManager &FactMgr, AnalysisDeclContext &ADC,
125 LifetimeSafetyReporter *Reporter) {
126 llvm::TimeTraceScope TimeProfile("LifetimeChecker");
127 LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter);
128}
129
130} // namespace clang::lifetimes::internal
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the clang::SourceLocation class and associated facilities.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a single basic block in a source-level CFG.
Definition CFG.h:605
This represents one expression.
Definition Expr.h:112
Encodes a location in the source.
llvm::ImmutableSet< LoanID > LoanSet
utils::ID< struct LoanTag > LoanID
Definition Loans.h:23
llvm::ImmutableMap< OriginID, LivenessInfo > LivenessMap
Definition LiveOrigins.h:74
void runLifetimeChecker(const LoanPropagationAnalysis &LoanPropagation, const LiveOriginsAnalysis &LiveOrigins, const FactManager &FactMgr, AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
Runs the lifetime checker, which detects use-after-free errors by examining loan expiration points an...
Definition Checker.cpp:122
static Confidence livenessKindToConfidence(LivenessKind K)
Definition Checker.cpp:29
Confidence
Enum to track the confidence level of a potential error.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
for(const auto &A :T->param_types())