1use std::fmt;
4
5#[derive(Debug, Clone)]
7pub struct FuzzResult {
8 pub target: String,
10 pub test_cases: u64,
12 pub failures: u64,
14 pub coverage_percent: f64,
16 pub failure_details: Vec<FuzzFailure>,
18 pub duration_secs: f64,
20}
21
22impl FuzzResult {
23 pub fn new(target: &str) -> Self {
25 Self {
26 target: target.to_string(),
27 test_cases: 0,
28 failures: 0,
29 coverage_percent: 0.0,
30 failure_details: Vec::new(),
31 duration_secs: 0.0,
32 }
33 }
34
35 pub fn record_success(&mut self) {
37 self.test_cases += 1;
38 }
39
40 pub fn record_failure(&mut self, input: String, error: String) {
42 self.test_cases += 1;
43 self.failures += 1;
44 self.failure_details.push(FuzzFailure { input, error });
45 }
46
47 pub fn passed(&self) -> bool {
49 self.failures == 0
50 }
51
52 pub fn failure_rate(&self) -> f64 {
54 if self.test_cases == 0 {
55 0.0
56 } else {
57 (self.failures as f64 / self.test_cases as f64) * 100.0
58 }
59 }
60}
61
62#[derive(Debug, Clone)]
64pub struct FuzzFailure {
65 pub input: String,
67 pub error: String,
69}
70
71#[derive(Debug, Clone, Default)]
73pub struct FuzzInputValidator {
74 pub max_string_len: usize,
76 pub max_numeric: f64,
78 pub min_numeric: f64,
80 pub allow_nan: bool,
82 pub allow_infinity: bool,
84 pub allow_negative: bool,
86 pub allow_zero: bool,
88}
89
90impl FuzzInputValidator {
91 pub fn new() -> Self {
93 Self {
94 max_string_len: 1024,
95 max_numeric: 1e15,
96 min_numeric: -1e15,
97 allow_nan: false,
98 allow_infinity: false,
99 allow_negative: true,
100 allow_zero: true,
101 }
102 }
103
104 pub fn validate_float(&self, value: f64) -> Result<f64, FuzzValidationError> {
106 if value.is_nan() && !self.allow_nan {
107 return Err(FuzzValidationError::NaN);
108 }
109 if value.is_infinite() && !self.allow_infinity {
110 return Err(FuzzValidationError::Infinity);
111 }
112 if value < 0.0 && !self.allow_negative {
113 return Err(FuzzValidationError::NegativeValue(value));
114 }
115 if value == 0.0 && !self.allow_zero {
116 return Err(FuzzValidationError::ZeroValue);
117 }
118 if value > self.max_numeric {
119 return Err(FuzzValidationError::TooLarge(value));
120 }
121 if value < self.min_numeric {
122 return Err(FuzzValidationError::TooSmall(value));
123 }
124 Ok(value)
125 }
126
127 pub fn validate_string<'a>(&self, value: &'a str) -> Result<&'a str, FuzzValidationError> {
129 if value.len() > self.max_string_len {
130 return Err(FuzzValidationError::StringTooLong(value.len()));
131 }
132 if value
134 .chars()
135 .any(|c| c.is_control() && c != '\n' && c != '\t')
136 {
137 return Err(FuzzValidationError::InvalidControlChars);
138 }
139 Ok(value)
140 }
141
142 pub fn validate_u64(&self, value: u64) -> Result<u64, FuzzValidationError> {
144 let max = self.max_numeric as u64;
145 if value > max {
146 return Err(FuzzValidationError::TooLarge(value as f64));
147 }
148 if value == 0 && !self.allow_zero {
149 return Err(FuzzValidationError::ZeroValue);
150 }
151 Ok(value)
152 }
153
154 pub fn positive_only() -> Self {
156 Self {
157 allow_negative: false,
158 allow_zero: false,
159 ..Self::new()
160 }
161 }
162
163 pub fn non_negative() -> Self {
165 Self {
166 allow_negative: false,
167 ..Self::new()
168 }
169 }
170
171 pub fn strict() -> Self {
173 Self {
174 allow_nan: false,
175 allow_infinity: false,
176 max_numeric: 1e12,
177 min_numeric: -1e12,
178 ..Self::new()
179 }
180 }
181}
182
183#[derive(Debug, Clone, PartialEq)]
185pub enum FuzzValidationError {
186 NaN,
188 Infinity,
190 NegativeValue(f64),
192 ZeroValue,
194 TooLarge(f64),
196 TooSmall(f64),
198 StringTooLong(usize),
200 InvalidControlChars,
202 IntegerOverflow,
204 DivisionByZero,
206 EmptyInput,
208 InvalidFormat(String),
210}
211
212impl fmt::Display for FuzzValidationError {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 match self {
215 FuzzValidationError::NaN => write!(f, "NaN value not allowed"),
216 FuzzValidationError::Infinity => write!(f, "Infinity value not allowed"),
217 FuzzValidationError::NegativeValue(v) => write!(f, "Negative value not allowed: {}", v),
218 FuzzValidationError::ZeroValue => write!(f, "Zero value not allowed"),
219 FuzzValidationError::TooLarge(v) => write!(f, "Value too large: {}", v),
220 FuzzValidationError::TooSmall(v) => write!(f, "Value too small: {}", v),
221 FuzzValidationError::StringTooLong(len) => write!(f, "String too long: {} chars", len),
222 FuzzValidationError::InvalidControlChars => write!(f, "Invalid control characters"),
223 FuzzValidationError::IntegerOverflow => write!(f, "Integer overflow"),
224 FuzzValidationError::DivisionByZero => write!(f, "Division by zero"),
225 FuzzValidationError::EmptyInput => write!(f, "Empty input"),
226 FuzzValidationError::InvalidFormat(s) => write!(f, "Invalid format: {}", s),
227 }
228 }
229}
230
231impl std::error::Error for FuzzValidationError {}