(
&mut self,
state: &State,
vm: &mut Vm,
target: &CortexmMultiStream,
exit: VmExit,
)
| 303 | } |
| 304 | |
| 305 | pub fn save( |
| 306 | &mut self, |
| 307 | state: &State, |
| 308 | vm: &mut Vm, |
| 309 | target: &CortexmMultiStream, |
| 310 | exit: VmExit, |
| 311 | ) -> anyhow::Result<()> { |
| 312 | let save_dir = match CrashKind::from(exit) { |
| 313 | CrashKind::Hang => { |
| 314 | self.print_crash_or_hang(vm, target, exit, "hang"); |
| 315 | match self.hangs.len() < self.save_limit { |
| 316 | true => self.hang_dir.as_ref(), |
| 317 | false => None, |
| 318 | } |
| 319 | } |
| 320 | _ => { |
| 321 | self.print_crash_or_hang(vm, target, exit, "crash"); |
| 322 | match self.crashes.len() < self.save_limit { |
| 323 | true => self.crash_dir.as_ref(), |
| 324 | false => None, |
| 325 | } |
| 326 | } |
| 327 | }; |
| 328 | |
| 329 | if let Some(dir) = save_dir { |
| 330 | let path = dir.join(format!("{}", icicle_fuzzing::gen_crash_key(vm, exit))); |
| 331 | std::fs::write(&path, state.input.to_bytes()) |
| 332 | .with_context(|| format!("failed to save to {}", path.display()))?; |
| 333 | } |
| 334 | |
| 335 | #[derive(serde::Serialize)] |
| 336 | struct CrashMetadata<'a> { |
| 337 | crashes: Vec<(&'a String, &'a CrashEntry)>, |
| 338 | hangs: Vec<(&'a String, &'a CrashEntry)>, |
| 339 | } |
| 340 | let mut metadata = CrashMetadata { |
| 341 | crashes: self.crashes.iter().collect(), |
| 342 | hangs: self.hangs.iter().collect(), |
| 343 | }; |
| 344 | metadata.crashes.sort_by_key(|(_, entry)| entry.callstack.last()); |
| 345 | metadata.hangs.sort_by_key(|(_, entry)| entry.callstack.last()); |
| 346 | std::fs::write(&self.metadata_path, serde_json::ser::to_vec(&metadata)?)?; |
| 347 | |
| 348 | Ok(()) |
| 349 | } |
| 350 | |
| 351 | fn print_crash_or_hang( |
| 352 | &self, |
no test coverage detected