neo_solidity/
security.rs

1//! Security Analysis Module
2//!
3//! Detects potential security vulnerabilities in Solidity code.
4
5use crate::error::{ErrorCode, FixSuggestion, SourceLocation};
6
7/// Security issue severity
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum SecuritySeverity {
10    Critical,
11    High,
12    Medium,
13    Low,
14    Info,
15}
16
17/// A detected security issue
18#[derive(Debug, Clone)]
19pub struct SecurityIssue {
20    pub severity: SecuritySeverity,
21    pub code: ErrorCode,
22    pub message: String,
23    pub location: SourceLocation,
24    pub suggestion: Option<FixSuggestion>,
25}
26
27impl SecurityIssue {
28    pub fn critical(code: ErrorCode, msg: impl Into<String>, loc: SourceLocation) -> Self {
29        Self {
30            severity: SecuritySeverity::Critical,
31            code,
32            message: msg.into(),
33            location: loc,
34            suggestion: None,
35        }
36    }
37
38    pub fn high(code: ErrorCode, msg: impl Into<String>, loc: SourceLocation) -> Self {
39        Self {
40            severity: SecuritySeverity::High,
41            code,
42            message: msg.into(),
43            location: loc,
44            suggestion: None,
45        }
46    }
47
48    pub fn with_suggestion(mut self, s: FixSuggestion) -> Self {
49        self.suggestion = Some(s);
50        self
51    }
52}
53
54/// Security checker
55#[derive(Default)]
56pub struct SecurityChecker {
57    issues: Vec<SecurityIssue>,
58}
59
60impl SecurityChecker {
61    pub fn new() -> Self {
62        Self::default()
63    }
64
65    pub fn add_issue(&mut self, issue: SecurityIssue) {
66        self.issues.push(issue);
67    }
68
69    pub fn issues(&self) -> &[SecurityIssue] {
70        &self.issues
71    }
72
73    pub fn has_critical(&self) -> bool {
74        self.issues
75            .iter()
76            .any(|i| i.severity == SecuritySeverity::Critical)
77    }
78
79    pub fn has_high(&self) -> bool {
80        self.issues
81            .iter()
82            .any(|i| i.severity == SecuritySeverity::High)
83    }
84
85    pub fn count_by_severity(&self, sev: SecuritySeverity) -> usize {
86        self.issues.iter().filter(|i| i.severity == sev).count()
87    }
88
89    pub fn clear(&mut self) {
90        self.issues.clear();
91    }
92}