|
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