panic_attacker/report/
generator.rs1use crate::types::*;
6use anyhow::Result;
7
8pub struct ReportGenerator;
9
10impl ReportGenerator {
11 pub fn new() -> Self {
12 Self
13 }
14
15 pub fn generate(
16 &self,
17 xray_report: XRayReport,
18 attack_results: Vec<AttackResult>,
19 ) -> Result<AssaultReport> {
20 let total_crashes = attack_results.iter().map(|r| r.crashes.len()).sum();
21
22 let total_signatures = attack_results
23 .iter()
24 .map(|r| r.signatures_detected.len())
25 .sum();
26
27 let overall_assessment = self.assess_results(&xray_report, &attack_results);
28
29 Ok(AssaultReport {
30 xray_report,
31 attack_results,
32 total_crashes,
33 total_signatures,
34 overall_assessment,
35 })
36 }
37
38 fn assess_results(&self, xray: &XRayReport, results: &[AttackResult]) -> OverallAssessment {
39 let mut critical_issues = Vec::new();
40 let mut recommendations = Vec::new();
41
42 let _total_attacks = results.len() as f64;
44 let _successful_attacks = results.iter().filter(|r| r.success).count() as f64;
45 let crash_count = results.iter().map(|r| r.crashes.len()).sum::<usize>() as f64;
46
47 let mut score = 100.0;
52 score -= crash_count * 10.0;
53 score -= xray
54 .weak_points
55 .iter()
56 .filter(|w| w.severity == Severity::Critical)
57 .count() as f64
58 * 20.0;
59 score -= (xray.statistics.unsafe_blocks as f64) * 5.0;
60
61 score = score.clamp(0.0, 100.0);
62
63 for result in results {
65 if !result.crashes.is_empty() {
66 critical_issues.push(format!(
67 "Program crashed under {:?} attack ({} crashes)",
68 result.axis,
69 result.crashes.len()
70 ));
71 }
72
73 for sig in &result.signatures_detected {
74 if sig.confidence > 0.8 {
75 critical_issues.push(format!(
76 "High-confidence {:?} detected (confidence: {:.2})",
77 sig.signature_type, sig.confidence
78 ));
79 }
80 }
81 }
82
83 if crash_count > 0.0 {
85 recommendations.push("Add comprehensive error handling for edge cases".to_string());
86 }
87
88 if xray.statistics.unwrap_calls > 10 {
89 recommendations.push("Replace unwrap() calls with proper error handling".to_string());
90 }
91
92 if xray.statistics.unsafe_blocks > 0 {
93 recommendations.push("Audit unsafe blocks for memory safety violations".to_string());
94 }
95
96 if results.iter().any(|r| {
97 r.signatures_detected
98 .iter()
99 .any(|s| matches!(s.signature_type, SignatureType::DataRace))
100 }) {
101 recommendations
102 .push("Add synchronization primitives to prevent data races".to_string());
103 }
104
105 if results.iter().any(|r| {
106 r.signatures_detected
107 .iter()
108 .any(|s| matches!(s.signature_type, SignatureType::Deadlock))
109 }) {
110 recommendations.push("Review lock ordering to prevent deadlocks".to_string());
111 }
112
113 if score < 50.0 {
114 recommendations.push("Consider comprehensive refactoring for robustness".to_string());
115 }
116
117 OverallAssessment {
118 robustness_score: score,
119 critical_issues,
120 recommendations,
121 }
122 }
123}
124
125impl Default for ReportGenerator {
126 fn default() -> Self {
127 Self::new()
128 }
129}