Skip to main content

xbp_analysis/application/rules/
unsafe_termination.rs

1use super::{base_caps, concepts_of, finding_from_concept};
2use crate::domain::concepts::ConceptKind;
3use crate::domain::model::LanguageModel;
4use crate::domain::rule::{Rule, RuleMeta};
5use crate::domain::types::{Confidence, Finding, Severity};
6use std::sync::OnceLock;
7
8#[derive(Default)]
9pub struct UnsafeTerminationRule;
10
11impl Rule for UnsafeTerminationRule {
12    fn meta(&self) -> &RuleMeta {
13        static META: OnceLock<RuleMeta> = OnceLock::new();
14        META.get_or_init(|| RuleMeta {
15            id: "unsafe-termination".into(),
16            name: "Unsafe termination".into(),
17            description: "Process or task may abort on recoverable errors (unwrap/expect/panic)."
18                .into(),
19            default_severity: Severity::High,
20            required_capabilities: base_caps(),
21            autofix_safe: false,
22        })
23    }
24
25    fn evaluate(&self, model: &LanguageModel) -> Vec<Finding> {
26        concepts_of(model, ConceptKind::Termination)
27            .map(|(lang, c)| {
28                let confidence = if c.tag == "unwrap" || c.tag == "expect" || c.tag == "panic" {
29                    Confidence::High
30                } else {
31                    Confidence::Medium
32                };
33                finding_from_concept(
34                    &self.meta().id,
35                    lang,
36                    c,
37                    Severity::High,
38                    confidence,
39                    format!("Unsafe termination via `{}`.", c.tag),
40                    "A recoverable error aborts the process or task, taking down the service.",
41                    "Return Result/Option, use map_err, or handle with explicit recovery.",
42                )
43            })
44            .collect()
45    }
46}