Skip to main content

panic_attacker/report/
generator.rs

1// SPDX-License-Identifier: PMPL-1.0-or-later
2
3//! Report generation logic
4
5use 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        // Calculate robustness score (0-100)
43        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        // Score formula: higher is better
48        // - Subtract 10 points for each crash
49        // - Subtract 20 points for critical weak points
50        // - Subtract 5 points for unsafe code
51        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        // Identify critical issues
64        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        // Generate recommendations
84        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}