save the incident and respawn the libfuzzer
(fuzzer_dir: &Path, executor: &Executor)
| 605 | |
| 606 | /// save the incident and respawn the libfuzzer |
| 607 | pub fn respawn_libfuzzer_process(fuzzer_dir: &Path, executor: &Executor) -> Result<Child> { |
| 608 | static ERROR_COUNT: OnceCell<RwLock<HashMap<u16, usize>>> = OnceCell::new(); |
| 609 | |
| 610 | let fuzzer = get_fuzzer_path(fuzzer_dir); |
| 611 | let fuzz_log = get_fuzzer_log(fuzzer_dir); |
| 612 | |
| 613 | let artifact = |
| 614 | parse_artifact_from_log(&fuzz_log).context(format!("parse artifact fail: {fuzz_log:?}"))?; |
| 615 | |
| 616 | if let Some(driver_id) = parse_driver_id(&artifact) { |
| 617 | log::info!("Found an error happened in driver: {driver_id}"); |
| 618 | |
| 619 | // if this driver error many times |
| 620 | let err_count = { |
| 621 | let error_count_map_guard = ERROR_COUNT.get_or_init(|| RwLock::new(HashMap::new())).read().unwrap(); |
| 622 | if let Some(value) = error_count_map_guard.get(&driver_id) { |
| 623 | *value |
| 624 | } else { |
| 625 | 1 |
| 626 | } |
| 627 | }; |
| 628 | |
| 629 | if let Ok(mut error_count_map_guard) = ERROR_COUNT.get_or_init(|| RwLock::new(HashMap::new())).write() { |
| 630 | *error_count_map_guard.entry(driver_id).or_default() += 1; |
| 631 | } |
| 632 | |
| 633 | let incident_dir = get_incident_dir(fuzzer_dir, driver_id); |
| 634 | save_the_incident(fuzzer_dir, &incident_dir, &artifact, None)?; |
| 635 | |
| 636 | if is_incident_reproducible(&incident_dir, &executor.deopt)? || err_count > 5 { |
| 637 | let fuzz_code: PathBuf = get_fuzzer_path(fuzzer_dir).with_extension("cc"); |
| 638 | mask_driver_from_fuzzer(&fuzz_code, driver_id)?; |
| 639 | executor.compile_lib_fuzzers(fuzzer_dir, &fuzzer, crate::execution::Compile::FUZZER)?; |
| 640 | } else { |
| 641 | std::fs::remove_dir_all(incident_dir)?; |
| 642 | } |
| 643 | log::warn!("{fuzzer_dir:?} found an error with id `{driver_id}` and re-execute"); |
| 644 | } |
| 645 | |
| 646 | let corpus: PathBuf = [fuzzer_dir.to_path_buf(), "corpus".into()].iter().collect(); |
| 647 | let child = executor.spawn_libfuzzer(&fuzzer, &corpus).context(format!( |
| 648 | "Fail to spawn libfuzzer process: {fuzzer:?} on {corpus:?}" |
| 649 | ))?; |
| 650 | Ok(child) |
| 651 | } |
| 652 | |
| 653 | pub mod sanitize_crash { |
| 654 | use std::{collections::HashSet, ffi::OsStr}; |
no test coverage detected