1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
// Copyright 2015 Keegan McAllister. // Copyright 2016 Corey Farwell. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // See `LICENSE` in this repository. use std::io::{self, Read}; use std::{panic, process}; /// Utility that reads a `Vec` of bytes from standard input (stdin) /// and passes it to `closure`. All panics that occur within /// `closure` will be treated as aborts. This is done so that /// AFL considers a panic to be a crash. /// /// # Examples /// /// ```no_run /// extern crate afl; /// # struct Image; /// # impl Image { /// # fn parse(_: &[u8]) {} /// # } /// /// fn main() { /// afl::read_stdio_bytes(|read| { /// Image::parse(&read) /// }) /// } /// ``` pub fn read_stdio_bytes<F>(closure: F) where F: Fn(Vec<u8>) + panic::RefUnwindSafe, { let mut input = vec![]; let result = io::stdin().read_to_end(&mut input); if result.is_err() { return; } let was_panic = panic::catch_unwind(|| { closure(input); }); if was_panic.is_err() { process::abort(); } } /// Utility that reads a `String` from standard input (stdin) and /// passes it to `closure`. If a `String` cannot be constructed from /// the data provided by standard input, `closure` will _not_ be /// called. All panics that occur within `closure` will be treated as /// aborts. This is done so that AFL considers a panic to be a crash. /// /// # Examples /// /// ```no_run /// extern crate afl; /// # struct Url; /// # impl Url { /// # fn parse(_: &str) {} /// # } /// /// fn main() { /// afl::read_stdio_string(|string| { /// Url::parse(&string) /// }) /// } /// ``` pub fn read_stdio_string<F>(closure: F) where F: Fn(String) + panic::RefUnwindSafe, { let mut input = String::new(); let result = io::stdin().read_to_string(&mut input); if result.is_err() { return; } let was_panic = panic::catch_unwind(|| { closure(input); }); if was_panic.is_err() { process::abort(); } } #[cfg(test)] mod test { /* use std::path::PathBuf; use std::process::{Command, Stdio}; use std::thread; use std::time; extern crate libc; extern crate tempdir; fn target_path() -> PathBuf { if PathBuf::from("../target/debug/cargo-afl-fuzz").exists() { PathBuf::from("../target/debug/") } else if PathBuf::from("target/debug/cargo-afl-fuzz").exists() { PathBuf::from("target/debug/") } else { panic!("Could not find cargo-afl-fuzz!"); } } #[test] fn test_cargo_afl_fuzz() { let temp_dir = tempdir::TempDir::new("aflrs").expect("Could not create temporary directory"); let temp_dir_path = temp_dir.path(); let mut child = Command::new(target_path().join("cargo-afl-fuzz")) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .arg("-i") .arg(".") .arg("-o") .arg(temp_dir_path) .arg(target_path().join("examples").join("hello")) .spawn() .expect("Could not run cargo-afl-fuzz"); thread::sleep(time::Duration::from_secs(7)); child.kill().unwrap(); assert!(temp_dir_path.join("fuzzer_stats").is_file()); } */ }