1use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7use std::time::Duration;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(rename_all = "lowercase")]
12pub enum Language {
13 Rust,
14 C,
15 Cpp,
16 Go,
17 Java,
18 Python,
19 JavaScript,
20 Ruby,
21 Unknown,
22}
23
24impl Language {
25 pub fn detect(path: &str) -> Self {
26 let ext = std::path::Path::new(path)
27 .extension()
28 .and_then(|s| s.to_str())
29 .unwrap_or("");
30
31 match ext {
32 "rs" => Language::Rust,
33 "c" | "h" => Language::C,
34 "cpp" | "cc" | "cxx" | "hpp" => Language::Cpp,
35 "go" => Language::Go,
36 "java" => Language::Java,
37 "py" => Language::Python,
38 "js" | "ts" => Language::JavaScript,
39 "rb" => Language::Ruby,
40 _ => Language::Unknown,
41 }
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
47pub enum Framework {
48 WebServer,
49 Database,
50 MessageQueue,
51 Cache,
52 FileSystem,
53 Networking,
54 Concurrent,
55 Unknown,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
60#[serde(rename_all = "lowercase")]
61pub enum AttackAxis {
62 Cpu,
63 Memory,
64 Disk,
65 Network,
66 Concurrency,
67 Time,
68}
69
70impl AttackAxis {
71 pub fn all() -> Vec<Self> {
72 vec![
73 AttackAxis::Cpu,
74 AttackAxis::Memory,
75 AttackAxis::Disk,
76 AttackAxis::Network,
77 AttackAxis::Concurrency,
78 AttackAxis::Time,
79 ]
80 }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct WeakPoint {
86 pub category: WeakPointCategory,
87 pub location: Option<String>,
88 pub severity: Severity,
89 pub description: String,
90 pub recommended_attack: Vec<AttackAxis>,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
94pub enum WeakPointCategory {
95 UncheckedAllocation,
96 UnboundedLoop,
97 BlockingIO,
98 UnsafeCode,
99 PanicPath,
100 RaceCondition,
101 DeadlockPotential,
102 ResourceLeak,
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
106pub enum Severity {
107 Low,
108 Medium,
109 High,
110 Critical,
111}
112
113impl std::fmt::Display for Severity {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 match self {
116 Severity::Low => write!(f, "LOW"),
117 Severity::Medium => write!(f, "MEDIUM"),
118 Severity::High => write!(f, "HIGH"),
119 Severity::Critical => write!(f, "CRITICAL"),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct BugSignature {
127 pub signature_type: SignatureType,
128 pub confidence: f64,
129 pub evidence: Vec<String>,
130 pub location: Option<String>,
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
134pub enum SignatureType {
135 UseAfterFree,
136 DoubleFree,
137 MemoryLeak,
138 Deadlock,
139 DataRace,
140 BufferOverflow,
141 IntegerOverflow,
142 NullPointerDeref,
143 UnhandledError,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct FileStatistics {
149 pub file_path: String,
150 pub lines: usize,
151 pub unsafe_blocks: usize,
152 pub panic_sites: usize,
153 pub unwrap_calls: usize,
154 pub allocation_sites: usize,
155 pub io_operations: usize,
156 pub threading_constructs: usize,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct XRayReport {
162 pub program_path: PathBuf,
163 pub language: Language,
164 pub frameworks: Vec<Framework>,
165 pub weak_points: Vec<WeakPoint>,
166 pub statistics: ProgramStatistics,
167 pub file_statistics: Vec<FileStatistics>,
168 pub recommended_attacks: Vec<AttackAxis>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct ProgramStatistics {
173 pub total_lines: usize,
174 pub unsafe_blocks: usize,
175 pub panic_sites: usize,
176 pub unwrap_calls: usize,
177 pub allocation_sites: usize,
178 pub io_operations: usize,
179 pub threading_constructs: usize,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct AttackConfig {
185 pub axes: Vec<AttackAxis>,
186 pub duration: Duration,
187 pub intensity: IntensityLevel,
188 pub target_programs: Vec<PathBuf>,
189 pub data_corpus: Option<PathBuf>,
190 pub parallel_attacks: bool,
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
194pub enum IntensityLevel {
195 Light,
196 Medium,
197 Heavy,
198 Extreme,
199}
200
201impl IntensityLevel {
202 pub fn multiplier(&self) -> f64 {
203 match self {
204 IntensityLevel::Light => 1.0,
205 IntensityLevel::Medium => 5.0,
206 IntensityLevel::Heavy => 10.0,
207 IntensityLevel::Extreme => 50.0,
208 }
209 }
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct AttackResult {
215 pub program: PathBuf,
216 pub axis: AttackAxis,
217 pub success: bool,
218 pub exit_code: Option<i32>,
219 pub duration: Duration,
220 pub peak_memory: u64,
221 pub crashes: Vec<CrashReport>,
222 pub signatures_detected: Vec<BugSignature>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct CrashReport {
227 pub timestamp: String,
228 pub signal: Option<String>,
229 pub backtrace: Option<String>,
230 pub stderr: String,
231 pub stdout: String,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct AssaultReport {
237 pub xray_report: XRayReport,
238 pub attack_results: Vec<AttackResult>,
239 pub total_crashes: usize,
240 pub total_signatures: usize,
241 pub overall_assessment: OverallAssessment,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct OverallAssessment {
246 pub robustness_score: f64,
247 pub critical_issues: Vec<String>,
248 pub recommendations: Vec<String>,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct AttackPattern {
254 pub name: String,
255 pub description: String,
256 pub applicable_axes: Vec<AttackAxis>,
257 pub applicable_languages: Vec<Language>,
258 pub applicable_frameworks: Vec<Framework>,
259 pub command_template: String,
260}
261
262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
264pub enum Fact {
265 Alloc {
266 var: String,
267 location: usize,
268 },
269 Free {
270 var: String,
271 location: usize,
272 },
273 Use {
274 var: String,
275 location: usize,
276 },
277 Lock {
278 mutex: String,
279 location: usize,
280 },
281 Unlock {
282 mutex: String,
283 location: usize,
284 },
285 ThreadSpawn {
286 id: String,
287 location: usize,
288 },
289 #[allow(dead_code)] ThreadJoin {
291 id: String,
292 location: usize,
293 },
294 Write {
295 var: String,
296 location: usize,
297 },
298 Read {
299 var: String,
300 location: usize,
301 },
302 #[allow(dead_code)] Ordering {
304 before: usize,
305 after: usize,
306 },
307}
308
309#[derive(Debug, Clone)]
311pub struct Rule {
312 pub name: String,
313 #[allow(dead_code)] pub head: Predicate,
315 #[allow(dead_code)] pub body: Vec<Predicate>,
317}
318
319#[derive(Debug, Clone, PartialEq, Eq)]
320pub enum Predicate {
321 UseAfterFree {
322 var: String,
323 use_loc: usize,
324 free_loc: usize,
325 },
326 DoubleFree {
327 var: String,
328 loc1: usize,
329 loc2: usize,
330 },
331 Deadlock {
332 m1: String,
333 m2: String,
334 },
335 DataRace {
336 var: String,
337 loc1: usize,
338 loc2: usize,
339 },
340 Fact(Fact),
341}