memscope_rs/analyzer/
detect.rs1use crate::analyzer::report::{LeakInfo, LeakReport, SafetyReport, UafReport};
4use crate::snapshot::ActiveAllocation;
5use crate::view::MemoryView;
6use tracing::{debug, info, warn};
7
8pub struct DetectionAnalysis {
12 view: MemoryView,
13}
14
15impl DetectionAnalysis {
16 pub fn from_view(view: &MemoryView) -> Self {
18 debug!("Creating DetectionAnalysis with {} allocations", view.len());
19 Self { view: view.clone() }
20 }
21
22 pub fn leaks(&self) -> LeakReport {
36 let allocations = self.view.allocations();
37 let leaked: Vec<&ActiveAllocation> = allocations
38 .into_iter()
39 .filter(|a| a.ptr.is_some())
40 .collect();
41
42 let leak_count = leaked.len();
43 let total_bytes: usize = leaked.iter().map(|a| a.size).sum();
44
45 if leak_count > 0 {
46 info!(
47 "Leak detection: found {} leaks totaling {} bytes",
48 leak_count, total_bytes
49 );
50 } else {
51 debug!("Leak detection: no leaks found");
52 }
53
54 LeakReport {
55 leak_count,
56 total_leaked_bytes: total_bytes,
57 leaked_allocations: leaked.into_iter().map(LeakInfo::from).collect(),
58 }
59 }
60
61 pub fn uaf(&self) -> UafReport {
77 debug!("UAF detection: not implemented, returning empty report");
86 UafReport::empty()
87 }
88
89 pub fn safety(&self) -> SafetyReport {
93 let allocations = self.view.allocations();
94 let report = SafetyReport::from_allocations(&allocations);
95 if report.issue_count > 0 {
96 warn!(
97 "Safety analysis: found {} potential safety issues",
98 report.issue_count
99 );
100 }
101 report
102 }
103
104 pub fn summary(&self) -> DetectionSummary {
106 let leaks = self.leaks();
107 let safety = self.safety();
108 DetectionSummary {
109 leak_count: leaks.leak_count,
110 leaked_bytes: leaks.total_leaked_bytes,
111 uaf_count: 0, safety_issues: safety.issue_count,
113 }
114 }
115}
116
117#[derive(Debug, Clone)]
119pub struct DetectionSummary {
120 pub leak_count: usize,
122 pub leaked_bytes: usize,
124 pub uaf_count: usize,
126 pub safety_issues: usize,
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 use crate::event_store::MemoryEvent;
134
135 #[test]
136 fn test_leak_detection() {
137 let events = vec![
138 MemoryEvent::allocate(0x1000, 64, 1),
139 MemoryEvent::allocate(0x2000, 128, 2),
140 MemoryEvent::deallocate(0x1000, 64, 1),
141 ];
142 let view = MemoryView::from_events(events);
143 let analysis = DetectionAnalysis::from_view(&view);
144 let leaks = analysis.leaks();
145 assert_eq!(leaks.leak_count, 1);
146 assert_eq!(leaks.total_leaked_bytes, 128);
147 }
148
149 #[test]
150 fn test_no_leaks() {
151 let events = vec![
152 MemoryEvent::allocate(0x1000, 64, 1),
153 MemoryEvent::deallocate(0x1000, 64, 1),
154 ];
155 let view = MemoryView::from_events(events);
156 let analysis = DetectionAnalysis::from_view(&view);
157 let leaks = analysis.leaks();
158 assert_eq!(leaks.leak_count, 0);
159 }
160
161 #[test]
162 fn test_uaf_returns_empty() {
163 let events = vec![
165 MemoryEvent::allocate(0x1000, 64, 1),
166 MemoryEvent::deallocate(0x1000, 64, 1),
167 ];
168 let view = MemoryView::from_events(events);
169 let analysis = DetectionAnalysis::from_view(&view);
170 let uaf = analysis.uaf();
171 assert_eq!(uaf.uaf_count, 0);
172 }
173}