diff --git a/libafl/src/stages/sync.rs b/libafl/src/stages/sync.rs index 2da7f23089..96d0c6d798 100644 --- a/libafl/src/stages/sync.rs +++ b/libafl/src/stages/sync.rs @@ -1,15 +1,13 @@ //! The [`SyncFromDiskStage`] is a stage that imports inputs from disk for e.g. sync with AFL -use alloc::borrow::{Cow, ToOwned}; -use core::{marker::PhantomData, time::Duration}; -use std::{ - fs, - path::{Path, PathBuf}, - time::SystemTime, +use alloc::{ + borrow::{Cow, ToOwned}, vec::Vec, }; +use core::{marker::PhantomData, time::Duration}; +use std::path::{Path, PathBuf}; -use libafl_bolts::{current_time, shmem::ShMemProvider, Named}; +use libafl_bolts::{current_time, fs::find_new_files_rec, shmem::ShMemProvider, Named}; use serde::{Deserialize, Serialize}; #[cfg(feature = "introspection")] @@ -25,6 +23,9 @@ use crate::{ Error, HasMetadata, HasNamedMetadata, }; +/// Default name for `SyncFromDiskStage`; derived from AFL++ +pub const SYNC_FROM_DISK_STAGE_NAME: &str = "sync"; + /// Metadata used to store information about disk sync time #[cfg_attr( any(not(feature = "serdeany_autoreg"), miri), @@ -51,46 +52,6 @@ impl SyncFromDiskMetadata { } } -/// Default name for `SyncFromDiskStage`; derived from AFL++ -pub const SYNC_FROM_DISK_STAGE_NAME: &str = "sync"; - -/// Finds new files in the given directory, taking the last time we looked at this path as parameter. -/// This method works recursively. -/// If `last` is `None`, it'll load all file. -fn find_new_files_rec>( - dir: P, - last_check: &Option, -) -> Result, Error> { - let mut new_files = Vec::::new(); - for entry in fs::read_dir(dir)? { - let entry = entry?; - let path = entry.path(); - let attributes = fs::metadata(&path); - - if attributes.is_err() { - continue; - } - - let attr = attributes?; - - if attr.is_file() && attr.len() > 0 { - if let Ok(time) = attr.modified() { - if let Some(last_check) = last_check { - if time.duration_since(SystemTime::UNIX_EPOCH).unwrap() < *last_check { - continue; - } - } - new_files.push(path.clone()); - } - } else if attr.is_dir() { - let dir_left_to_sync = find_new_files_rec(&entry.path(), last_check)?; - new_files.extend(dir_left_to_sync); - } - } - - Ok(new_files) -} - /// A stage that loads testcases from disk to sync with other fuzzers such as AFL++ #[derive(Debug)] pub struct SyncFromDiskStage { diff --git a/libafl_bolts/src/fs.rs b/libafl_bolts/src/fs.rs index 2c2257d0c2..9ffcf38b75 100644 --- a/libafl_bolts/src/fs.rs +++ b/libafl_bolts/src/fs.rs @@ -1,11 +1,15 @@ //! `LibAFL` functionality for filesystem interaction -#[cfg(feature = "std")] -use alloc::borrow::ToOwned; use alloc::rc::Rc; +#[cfg(feature = "std")] +use alloc::{borrow::ToOwned, vec::Vec}; use core::cell::RefCell; +#[cfg(feature = "std")] +use core::time::Duration; #[cfg(unix)] use std::os::unix::prelude::{AsRawFd, RawFd}; +#[cfg(feature = "std")] +use std::time::SystemTime; use std::{ fs::{self, remove_file, File, OpenOptions}, io::{Seek, Write}, @@ -140,6 +144,44 @@ impl InputFile { } } +/// Finds new files in the given directory, taking the last time we looked at this path as parameter. +/// This method works recursively. +/// If `last` is `None`, it'll load all file. +#[cfg(feature = "std")] +pub fn find_new_files_rec>( + dir: P, + last_check: &Option, +) -> Result, Error> { + let mut new_files = Vec::::new(); + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + let attributes = fs::metadata(&path); + + if attributes.is_err() { + continue; + } + + let attr = attributes?; + + if attr.is_file() && attr.len() > 0 { + if let Ok(time) = attr.modified() { + if let Some(last_check) = last_check { + if time.duration_since(SystemTime::UNIX_EPOCH).unwrap() < *last_check { + continue; + } + } + new_files.push(path.clone()); + } + } else if attr.is_dir() { + let dir_left_to_sync = find_new_files_rec(entry.path(), last_check)?; + new_files.extend(dir_left_to_sync); + } + } + + Ok(new_files) +} + #[cfg(feature = "std")] impl Drop for InputFile { fn drop(&mut self) {