Expose find_new_files_rec in libafl_bolts::fs (#2404)

This commit is contained in:
Dominik Maier 2024-07-16 04:47:03 +02:00 committed by GitHub
parent dc93f6c186
commit 4370a84bd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 49 deletions

View File

@ -1,15 +1,13 @@
//! The [`SyncFromDiskStage`] is a stage that imports inputs from disk for e.g. sync with AFL //! The [`SyncFromDiskStage`] is a stage that imports inputs from disk for e.g. sync with AFL
use alloc::borrow::{Cow, ToOwned}; use alloc::{
use core::{marker::PhantomData, time::Duration}; borrow::{Cow, ToOwned},
use std::{
fs,
path::{Path, PathBuf},
time::SystemTime,
vec::Vec, 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}; use serde::{Deserialize, Serialize};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
@ -25,6 +23,9 @@ use crate::{
Error, HasMetadata, HasNamedMetadata, 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 /// Metadata used to store information about disk sync time
#[cfg_attr( #[cfg_attr(
any(not(feature = "serdeany_autoreg"), miri), 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<P: AsRef<Path>>(
dir: P,
last_check: &Option<Duration>,
) -> Result<Vec<PathBuf>, Error> {
let mut new_files = Vec::<PathBuf>::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++ /// A stage that loads testcases from disk to sync with other fuzzers such as AFL++
#[derive(Debug)] #[derive(Debug)]
pub struct SyncFromDiskStage<CB, E, EM, Z> { pub struct SyncFromDiskStage<CB, E, EM, Z> {

View File

@ -1,11 +1,15 @@
//! `LibAFL` functionality for filesystem interaction //! `LibAFL` functionality for filesystem interaction
#[cfg(feature = "std")]
use alloc::borrow::ToOwned;
use alloc::rc::Rc; use alloc::rc::Rc;
#[cfg(feature = "std")]
use alloc::{borrow::ToOwned, vec::Vec};
use core::cell::RefCell; use core::cell::RefCell;
#[cfg(feature = "std")]
use core::time::Duration;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::prelude::{AsRawFd, RawFd}; use std::os::unix::prelude::{AsRawFd, RawFd};
#[cfg(feature = "std")]
use std::time::SystemTime;
use std::{ use std::{
fs::{self, remove_file, File, OpenOptions}, fs::{self, remove_file, File, OpenOptions},
io::{Seek, Write}, 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<P: AsRef<Path>>(
dir: P,
last_check: &Option<Duration>,
) -> Result<Vec<PathBuf>, Error> {
let mut new_files = Vec::<PathBuf>::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")] #[cfg(feature = "std")]
impl Drop for InputFile { impl Drop for InputFile {
fn drop(&mut self) { fn drop(&mut self) {