use std::fs;
use std::io::Write as IoWrite;
use std::path::{Path, PathBuf};
use time;
use crate::core::Executor;
use crate::corpus::*;
use crate::error::*;
use crate::loader::*;
use crate::utils::*;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ExitKind {
Continue,
EarlyFunctionReturn,
Crash(String),
Timeout,
Exit,
}
pub struct CrashHandler {
path: PathBuf,
rand: Random,
}
impl CrashHandler {
pub fn new(path: impl AsRef<Path>, rand: Random) -> Result<Self> {
fs::create_dir_all(&path)?;
Ok(Self {
path: path.as_ref().to_owned(),
rand,
})
}
fn crash_filepath(&mut self) -> (PathBuf, PathBuf) {
let fmt =
time::format_description::parse("[year][month][day]-[hour][minute][second]").unwrap();
let path = self.path.join(PathBuf::from(format!(
"crash_{}_{}",
time::OffsetDateTime::now_utc().format(&fmt).unwrap(),
self.rand.str(10),
)));
let mut path_info = path.clone();
path_info.set_extension("info");
(path, path_info)
}
fn timeout_filepath(&mut self) -> (PathBuf, PathBuf) {
let fmt =
time::format_description::parse("[year][month][day]-[hour][minute][second]").unwrap();
let path = self.path.join(PathBuf::from(format!(
"timeout_{}_{}",
time::OffsetDateTime::now_utc().format(&fmt).unwrap(),
self.rand.str(10),
)));
let mut path_info = path.clone();
path_info.set_extension("info");
(path, path_info)
}
pub fn store_crash<L: Loader + Loader<LD = LD> + Loader<GD = GD>, LD: Clone, GD: Clone>(
&mut self,
loader: &L,
title: &str,
tc: &Testcase,
executor: &Executor<L, LD, GD>,
is_timeout: bool,
) -> Result<()> {
let (filepath, filepath_info) = if is_timeout {
self.crash_filepath()
} else {
self.timeout_filepath()
};
let mut crash_info = fs::OpenOptions::new()
.write(true)
.create(true)
.open(filepath_info)?;
let crash_str = loader.format_crash(title, tc, executor, is_timeout)?;
crash_info.write_all(crash_str.as_bytes())?;
let mut crash = fs::OpenOptions::new()
.write(true)
.create(true)
.open(filepath)?;
crash.write_all(tc.get_data())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crash_filepath() {
let mut rand = Random::new(1);
let mut handler = CrashHandler::new("/tmp/crashes/", rand.split()).unwrap();
println!("{:?}", handler.crash_filepath());
println!("{:?}", handler.timeout_filepath());
}
}