
* Introduce libafl-fuzz * fix corpus file path * simplify SeedFeedback * fix incorrect comment * add clap::ValueEnum to PowerSchedule as an optional derive if clap is enabled * UnixShMemProvider replaced with StdShMemProvider for libafl-fuzz * remove io_error_more feature constraint * libafl-fuzz: make Ok(()) unreachable in CentralizedLauncher * libafl-fuzz: make harness_input_stdin to harness_input_type with &'static * libafl-fuzz: move each feedback to it's own file * make run_fuzzer_with_stage into a function. use CachedOnDiskCorpus instead of OnDiskCorpus for Corpora remove utils file * remove unecessary clone * libafl-fuzz: cleanup AFLStatsStage * move peak_rss_mb to libafl_bolts * parse envs by hand * add sensible defaults for map size and broker port * fix test.sh and corpus_id padding * add Makefile.toml * libafl-fuzz update test suite * libafl-fuzz: clippy * rename peak_rss_mb to peak_rss_mb_children * remove minor version constraint for clap * libafl-fuzz: fix ELF check and instrumentation check in check_binary * libafl-fuzz: improve Makefile.toml * simplify fuzzer and cleanup typos * libafl-fuzz: load corpus entries in a multicore fashion * libafl-fuzz: create output dir if not exists (non-racey) * libafl-fuzz: add sequential scheduling support libafl-fuzz: add cmplog options libafl-fuzz: add test-cmplog.c to CI * rename peak_rss_mb_children to peak_rss_mb_child_processes * fix race condition in SyncFromDiskStage, add interval based checking and support for multiple directories. libafl-fuzz: add support for syncing with foreign fuzzers * update README * implement AflScheduler for QueueScheduler. Add queue_cycles field to AflScheduler * libafl-fuzz: remove dependecy on SchedulerMetadata for AflStatsStage * clippy * remove queue_cycles from AflScheduler into int's own trait. libafl-fuzz: simplify map observer tracking * clippy * libafl-fuzz: disable cmplog check in CI for now * add missing constraints for libafl_qemu executor * clippy * libafl-fuzz: improve Makefile libafl-fuzz: clippy * libafl-fuzz: misc * misc typos, beautify --------- Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com> Co-authored-by: Dominik Maier <domenukk@gmail.com>
156 lines
5.4 KiB
Rust
156 lines
5.4 KiB
Rust
use std::{collections::HashMap, path::PathBuf, time::Duration};
|
|
|
|
use libafl::Error;
|
|
use libafl_bolts::core_affinity::Cores;
|
|
|
|
use crate::Opt;
|
|
|
|
pub fn parse_envs(opt: &mut Opt) -> Result<(), Error> {
|
|
if let Ok(res) = std::env::var("AFL_CORES") {
|
|
opt.cores = Some(Cores::from_cmdline(&res)?);
|
|
} else {
|
|
return Err(Error::illegal_argument("Missing AFL_CORES"));
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_INPUT_LEN_MAX") {
|
|
opt.max_input_len = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_INPUT_LEN_MIN") {
|
|
opt.min_input_len = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_BENCH_JUST_ONE") {
|
|
opt.bench_just_one = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_BENCH_UNTIL_CRASH") {
|
|
opt.bench_until_crash = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_HANG_TMOUT") {
|
|
opt.hang_timeout = res.parse()?;
|
|
} else {
|
|
opt.hang_timeout = 100;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_DEBUG_CHILD") {
|
|
opt.debug_child = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_PERSISTENT") {
|
|
opt.is_persistent = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_NO_AUTODICT") {
|
|
opt.no_autodict = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_MAP_SIZE") {
|
|
let map_size = res.parse()?;
|
|
validate_map_size(map_size)?;
|
|
opt.map_size = Some(map_size);
|
|
};
|
|
if let Ok(res) = std::env::var("AFL_IGNORE_TIMEOUT") {
|
|
opt.ignore_timeouts = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_TMPDIR") {
|
|
opt.cur_input_dir = Some(PathBuf::from(res));
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_CRASH_EXITCODE") {
|
|
opt.crash_exitcode = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_TARGET_ENV") {
|
|
opt.target_env = parse_target_env(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_CYCLE_SCHEDULES") {
|
|
opt.cycle_schedules = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_CMPLOG_ONLY_NEW") {
|
|
opt.cmplog_only_new = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_PRELOAD") {
|
|
opt.afl_preload = Some(res);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_SKIP_BIN_CHECK") {
|
|
opt.skip_bin_check = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_AUTORESUME") {
|
|
opt.auto_resume = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_DEFER_FORKSRV") {
|
|
opt.defer_forkserver = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_FUZZER_STATS_UPDATE_INTERVAL") {
|
|
opt.stats_interval = res.parse()?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_BROKER_PORT") {
|
|
opt.broker_port = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_EXIT_ON_SEED_ISSUES") {
|
|
opt.exit_on_seed_issues = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_IGNORE_SEED_ISSUES") {
|
|
opt.ignore_seed_issues = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_CRASHING_SEED_AS_NEW_CRASH") {
|
|
opt.crash_seed_as_new_crash = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_FRIDA_PERSISTENT_ADDR") {
|
|
opt.frida_persistent_addr = Some(res);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_QEMU_CUSTOM_BIN") {
|
|
opt.qemu_custom_bin = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_CS_CUSTOM_BIN") {
|
|
opt.cs_custom_bin = parse_bool(&res)?;
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_KILL_SIGNAL") {
|
|
opt.kill_signal = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_KILL_SIGNAL") {
|
|
opt.kill_signal = Some(res.parse()?);
|
|
}
|
|
if let Ok(res) = std::env::var("AFL_SYNC_TIME") {
|
|
opt.foreign_sync_interval = Duration::from_secs(res.parse::<u64>()? * 60);
|
|
} else {
|
|
opt.foreign_sync_interval = Duration::from_secs(AFL_DEFAULT_FOREIGN_SYNC_INTERVAL);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn parse_bool(val: &str) -> Result<bool, Error> {
|
|
match val {
|
|
"1" => Ok(true),
|
|
"0" => Ok(false),
|
|
_ => Err(Error::illegal_argument(
|
|
"boolean values must be either 1 for true or 0 for false",
|
|
)),
|
|
}
|
|
}
|
|
|
|
/// parse `AFL_TARGET_ENV`; expects: FOO=BAR TEST=ASD
|
|
fn parse_target_env(s: &str) -> Result<Option<HashMap<String, String>>, Error> {
|
|
let env_regex = regex::Regex::new(r"([^\s=]+)\s*=\s*([^\s]+)").unwrap();
|
|
let mut target_env = HashMap::new();
|
|
for vars in env_regex.captures_iter(s) {
|
|
target_env.insert(
|
|
vars.get(1)
|
|
.ok_or(Error::illegal_argument("invalid AFL_TARGET_ENV format"))?
|
|
.as_str()
|
|
.to_string(),
|
|
vars.get(2)
|
|
.ok_or(Error::illegal_argument("invalid AFL_TARGET_ENV format"))?
|
|
.as_str()
|
|
.to_string(),
|
|
);
|
|
}
|
|
Ok(Some(target_env))
|
|
}
|
|
|
|
fn validate_map_size(map_size: usize) -> Result<usize, Error> {
|
|
if map_size > AFL_MAP_SIZE_MIN && map_size < AFL_MAP_SIZE_MAX {
|
|
Ok(map_size)
|
|
} else {
|
|
Err(Error::illegal_argument(format!(
|
|
"AFL_MAP_SIZE not in range {AFL_MAP_SIZE_MIN} (2 ^ 3) - {AFL_MAP_SIZE_MAX} (2 ^ 30)",
|
|
)))
|
|
}
|
|
}
|
|
|
|
const AFL_MAP_SIZE_MIN: usize = usize::pow(2, 3);
|
|
const AFL_MAP_SIZE_MAX: usize = usize::pow(2, 30);
|
|
const AFL_DEFAULT_FOREIGN_SYNC_INTERVAL: u64 = 20 * 60;
|
|
pub const AFL_DEFAULT_MAP_SIZE: usize = 65536;
|