use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Language {
Rust,
C,
Cpp,
Go,
Java,
Python,
JavaScript,
Ruby,
Unknown,
}
impl Language {
pub fn detect(path: &str) -> Self {
let ext = std::path::Path::new(path)
.extension()
.and_then(|s| s.to_str())
.unwrap_or("");
match ext {
"rs" => Language::Rust,
"c" | "h" => Language::C,
"cpp" | "cc" | "cxx" | "hpp" => Language::Cpp,
"go" => Language::Go,
"java" => Language::Java,
"py" => Language::Python,
"js" | "ts" => Language::JavaScript,
"rb" => Language::Ruby,
_ => Language::Unknown,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Framework {
WebServer,
Database,
MessageQueue,
Cache,
FileSystem,
Networking,
Concurrent,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AttackAxis {
Cpu,
Memory,
Disk,
Network,
Concurrency,
Time,
}
impl AttackAxis {
pub fn all() -> Vec<Self> {
vec![
AttackAxis::Cpu,
AttackAxis::Memory,
AttackAxis::Disk,
AttackAxis::Network,
AttackAxis::Concurrency,
AttackAxis::Time,
]
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeakPoint {
pub category: WeakPointCategory,
pub location: Option<String>,
pub severity: Severity,
pub description: String,
pub recommended_attack: Vec<AttackAxis>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum WeakPointCategory {
UncheckedAllocation,
UnboundedLoop,
BlockingIO,
UnsafeCode,
PanicPath,
RaceCondition,
DeadlockPotential,
ResourceLeak,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Severity {
Low,
Medium,
High,
Critical,
}
impl std::fmt::Display for Severity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Severity::Low => write!(f, "LOW"),
Severity::Medium => write!(f, "MEDIUM"),
Severity::High => write!(f, "HIGH"),
Severity::Critical => write!(f, "CRITICAL"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BugSignature {
pub signature_type: SignatureType,
pub confidence: f64,
pub evidence: Vec<String>,
pub location: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SignatureType {
UseAfterFree,
DoubleFree,
MemoryLeak,
Deadlock,
DataRace,
BufferOverflow,
IntegerOverflow,
NullPointerDeref,
UnhandledError,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileStatistics {
pub file_path: String,
pub lines: usize,
pub unsafe_blocks: usize,
pub panic_sites: usize,
pub unwrap_calls: usize,
pub allocation_sites: usize,
pub io_operations: usize,
pub threading_constructs: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct XRayReport {
pub program_path: PathBuf,
pub language: Language,
pub frameworks: Vec<Framework>,
pub weak_points: Vec<WeakPoint>,
pub statistics: ProgramStatistics,
pub file_statistics: Vec<FileStatistics>,
pub recommended_attacks: Vec<AttackAxis>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramStatistics {
pub total_lines: usize,
pub unsafe_blocks: usize,
pub panic_sites: usize,
pub unwrap_calls: usize,
pub allocation_sites: usize,
pub io_operations: usize,
pub threading_constructs: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttackConfig {
pub axes: Vec<AttackAxis>,
pub duration: Duration,
pub intensity: IntensityLevel,
pub target_programs: Vec<PathBuf>,
pub data_corpus: Option<PathBuf>,
pub parallel_attacks: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IntensityLevel {
Light,
Medium,
Heavy,
Extreme,
}
impl IntensityLevel {
pub fn multiplier(&self) -> f64 {
match self {
IntensityLevel::Light => 1.0,
IntensityLevel::Medium => 5.0,
IntensityLevel::Heavy => 10.0,
IntensityLevel::Extreme => 50.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttackResult {
pub program: PathBuf,
pub axis: AttackAxis,
pub success: bool,
pub exit_code: Option<i32>,
pub duration: Duration,
pub peak_memory: u64,
pub crashes: Vec<CrashReport>,
pub signatures_detected: Vec<BugSignature>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrashReport {
pub timestamp: String,
pub signal: Option<String>,
pub backtrace: Option<String>,
pub stderr: String,
pub stdout: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssaultReport {
pub xray_report: XRayReport,
pub attack_results: Vec<AttackResult>,
pub total_crashes: usize,
pub total_signatures: usize,
pub overall_assessment: OverallAssessment,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OverallAssessment {
pub robustness_score: f64,
pub critical_issues: Vec<String>,
pub recommendations: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttackPattern {
pub name: String,
pub description: String,
pub applicable_axes: Vec<AttackAxis>,
pub applicable_languages: Vec<Language>,
pub applicable_frameworks: Vec<Framework>,
pub command_template: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Fact {
Alloc {
var: String,
location: usize,
},
Free {
var: String,
location: usize,
},
Use {
var: String,
location: usize,
},
Lock {
mutex: String,
location: usize,
},
Unlock {
mutex: String,
location: usize,
},
ThreadSpawn {
id: String,
location: usize,
},
#[allow(dead_code)] ThreadJoin {
id: String,
location: usize,
},
Write {
var: String,
location: usize,
},
Read {
var: String,
location: usize,
},
#[allow(dead_code)] Ordering {
before: usize,
after: usize,
},
}
#[derive(Debug, Clone)]
pub struct Rule {
pub name: String,
#[allow(dead_code)] pub head: Predicate,
#[allow(dead_code)] pub body: Vec<Predicate>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Predicate {
UseAfterFree {
var: String,
use_loc: usize,
free_loc: usize,
},
DoubleFree {
var: String,
loc1: usize,
loc2: usize,
},
Deadlock {
m1: String,
m2: String,
},
DataRace {
var: String,
loc1: usize,
loc2: usize,
},
Fact(Fact),
}