|
6 | 6 | // |
7 | 7 | //===----------------------------------------------------------------------===// |
8 | 8 | // |
9 | | -// This file defines the LifetimeChecker, which detects use-after-free errors |
10 | | -// by checking if live origins hold loans that have expired. It combines the |
11 | | -// results of loan propagation and liveness analysis to report violations with |
12 | | -// appropriate confidence levels. |
| 9 | +// This file provides the entry point for lifetime checking, which detects |
| 10 | +// use-after-free errors by checking if live origins hold loans that have |
| 11 | +// expired. |
13 | 12 | // |
14 | 13 | //===----------------------------------------------------------------------===// |
15 | 14 | #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_CHECKER_H |
16 | 15 | #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_CHECKER_H |
17 | 16 |
|
18 | | -#include "clang/AST/Decl.h" |
19 | | -#include "clang/AST/Expr.h" |
20 | 17 | #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h" |
21 | 18 | #include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h" |
22 | 19 | #include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h" |
23 | | -#include "clang/Analysis/Analyses/LifetimeSafety/Loans.h" |
24 | 20 | #include "clang/Analysis/Analyses/LifetimeSafety/Reporter.h" |
25 | | -#include "clang/Analysis/Analyses/PostOrderCFGView.h" |
26 | | -#include "clang/Analysis/AnalysisDeclContext.h" |
27 | | -#include "clang/Analysis/CFG.h" |
28 | | -#include "llvm/Support/ErrorHandling.h" |
29 | | -#include "llvm/Support/TimeProfiler.h" |
30 | 21 |
|
31 | | -namespace clang::lifetimes { |
| 22 | +namespace clang { |
| 23 | +namespace lifetimes { |
32 | 24 | namespace internal { |
33 | 25 |
|
34 | | -// ========================================================================= // |
35 | | -// Lifetime checker and Error reporter |
36 | | -// ========================================================================= // |
| 26 | +/// Runs the lifetime checker, which detects use-after-free errors by |
| 27 | +/// examining loan expiration points and checking if any live origins hold |
| 28 | +/// the expired loan. |
| 29 | +void runLifetimeChecker(LoanPropagationAnalysis &LoanPropagation, |
| 30 | + LiveOriginAnalysis &LiveOrigins, FactManager &FactMgr, |
| 31 | + AnalysisDeclContext &ADC, |
| 32 | + LifetimeSafetyReporter *Reporter); |
37 | 33 |
|
38 | | -/// Struct to store the complete context for a potential lifetime violation. |
39 | | -struct PendingWarning { |
40 | | - SourceLocation ExpiryLoc; // Where the loan expired. |
41 | | - const Expr *UseExpr; // Where the origin holding this loan was used. |
42 | | - Confidence ConfidenceLevel; |
43 | | -}; |
44 | | - |
45 | | -class LifetimeChecker { |
46 | | -private: |
47 | | - llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap; |
48 | | - LoanPropagationAnalysis &LoanPropagation; |
49 | | - LiveOriginAnalysis &LiveOrigins; |
50 | | - FactManager &FactMgr; |
51 | | - AnalysisDeclContext &ADC; |
52 | | - LifetimeSafetyReporter *Reporter; |
53 | | - |
54 | | -public: |
55 | | - LifetimeChecker(LoanPropagationAnalysis &LPA, LiveOriginAnalysis &LOA, |
56 | | - FactManager &FM, AnalysisDeclContext &ADC, |
57 | | - LifetimeSafetyReporter *Reporter) |
58 | | - : LoanPropagation(LPA), LiveOrigins(LOA), FactMgr(FM), ADC(ADC), |
59 | | - Reporter(Reporter) {} |
60 | | - |
61 | | - void run() { |
62 | | - llvm::TimeTraceScope TimeProfile("LifetimeChecker"); |
63 | | - for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) |
64 | | - for (const Fact *F : FactMgr.getFacts(B)) |
65 | | - if (const auto *EF = F->getAs<ExpireFact>()) |
66 | | - checkExpiry(EF); |
67 | | - issuePendingWarnings(); |
68 | | - } |
69 | | - |
70 | | - /// Checks for use-after-free errors when a loan expires. |
71 | | - /// |
72 | | - /// This method examines all live origins at the expiry point and determines |
73 | | - /// if any of them hold the expiring loan. If so, it creates a pending |
74 | | - /// warning with the appropriate confidence level based on the liveness |
75 | | - /// information. The confidence reflects whether the origin is definitely |
76 | | - /// or maybe live at this point. |
77 | | - /// |
78 | | - /// Note: This implementation considers only the confidence of origin |
79 | | - /// liveness. Future enhancements could also consider the confidence of loan |
80 | | - /// propagation (e.g., a loan may only be held on some execution paths). |
81 | | - void checkExpiry(const ExpireFact *EF) { |
82 | | - LoanID ExpiredLoan = EF->getLoanID(); |
83 | | - LivenessMap Origins = LiveOrigins.getLiveOrigins(EF); |
84 | | - Confidence CurConfidence = Confidence::None; |
85 | | - const UseFact *BadUse = nullptr; |
86 | | - for (auto &[OID, LiveInfo] : Origins) { |
87 | | - LoanSet HeldLoans = LoanPropagation.getLoans(OID, EF); |
88 | | - if (!HeldLoans.contains(ExpiredLoan)) |
89 | | - continue; |
90 | | - // Loan is defaulted. |
91 | | - Confidence NewConfidence = livenessKindToConfidence(LiveInfo.Kind); |
92 | | - if (CurConfidence < NewConfidence) { |
93 | | - CurConfidence = NewConfidence; |
94 | | - BadUse = LiveInfo.CausingUseFact; |
95 | | - } |
96 | | - } |
97 | | - if (!BadUse) |
98 | | - return; |
99 | | - // We have a use-after-free. |
100 | | - Confidence LastConf = FinalWarningsMap.lookup(ExpiredLoan).ConfidenceLevel; |
101 | | - if (LastConf >= CurConfidence) |
102 | | - return; |
103 | | - FinalWarningsMap[ExpiredLoan] = {/*ExpiryLoc=*/EF->getExpiryLoc(), |
104 | | - /*UseExpr=*/BadUse->getUseExpr(), |
105 | | - /*ConfidenceLevel=*/CurConfidence}; |
106 | | - } |
107 | | - |
108 | | - static Confidence livenessKindToConfidence(LivenessKind K) { |
109 | | - switch (K) { |
110 | | - case LivenessKind::Must: |
111 | | - return Confidence::Definite; |
112 | | - case LivenessKind::Maybe: |
113 | | - return Confidence::Maybe; |
114 | | - case LivenessKind::Dead: |
115 | | - return Confidence::None; |
116 | | - } |
117 | | - llvm_unreachable("unknown liveness kind"); |
118 | | - } |
119 | | - |
120 | | - void issuePendingWarnings() { |
121 | | - if (!Reporter) |
122 | | - return; |
123 | | - for (const auto &[LID, Warning] : FinalWarningsMap) { |
124 | | - const Loan &L = FactMgr.getLoanMgr().getLoan(LID); |
125 | | - const Expr *IssueExpr = L.IssueExpr; |
126 | | - Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr, |
127 | | - Warning.ExpiryLoc, Warning.ConfidenceLevel); |
128 | | - } |
129 | | - } |
130 | | -}; |
131 | 34 | } // namespace internal |
132 | | -} // namespace clang::lifetimes |
| 35 | +} // namespace lifetimes |
| 36 | +} // namespace clang |
133 | 37 |
|
134 | 38 | #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_CHECKER_H |
0 commit comments