Use Arc<()> to ref-counting InputFile (#3240)

* clean lib_bolts::fs

* clippy

* avoid racy
This commit is contained in:
lazymio 2025-05-16 23:06:23 +08:00 committed by GitHub
parent 7a9f46b9fb
commit be74774463
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,14 +1,14 @@
//! `LibAFL` functionality for filesystem interaction //! `LibAFL` functionality for filesystem interaction
#[cfg(feature = "std")]
use alloc::{borrow::ToOwned, vec::Vec};
use alloc::{rc::Rc, string::String};
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 alloc::string::String;
use alloc::sync::Arc;
use alloc::{borrow::ToOwned, vec::Vec};
use core::time::Duration;
use crate::Error;
use std::time::SystemTime; use std::time::SystemTime;
use std::{ use std::{
fs::{self, File, OpenOptions, remove_file}, fs::{self, File, OpenOptions, remove_file},
@ -16,8 +16,6 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use crate::Error;
/// The default filename to use to deliver testcases to the target /// The default filename to use to deliver testcases to the target
pub const INPUTFILE_STD: &str = ".cur_input"; pub const INPUTFILE_STD: &str = ".cur_input";
@ -62,7 +60,6 @@ where
/// An [`InputFile`] to write fuzzer input to. /// An [`InputFile`] to write fuzzer input to.
/// The target/forkserver will read from this file. /// The target/forkserver will read from this file.
#[cfg(feature = "std")]
#[derive(Debug)] #[derive(Debug)]
pub struct InputFile { pub struct InputFile {
/// The filename/path too this [`InputFile`] /// The filename/path too this [`InputFile`]
@ -71,7 +68,7 @@ pub struct InputFile {
pub file: File, pub file: File,
/// The ref count for this [`InputFile`]. /// The ref count for this [`InputFile`].
/// Once it reaches 0, the underlying [`File`] will be removed. /// Once it reaches 0, the underlying [`File`] will be removed.
pub rc: Rc<RefCell<usize>>, pub rc: Arc<()>,
} }
impl Eq for InputFile {} impl Eq for InputFile {}
@ -84,11 +81,6 @@ impl PartialEq for InputFile {
impl Clone for InputFile { impl Clone for InputFile {
fn clone(&self) -> Self { fn clone(&self) -> Self {
{
let mut rc = self.rc.borrow_mut();
assert_ne!(*rc, usize::MAX, "InputFile rc overflow");
*rc += 1;
}
Self { Self {
path: self.path.clone(), path: self.path.clone(),
file: self.file.try_clone().unwrap(), file: self.file.try_clone().unwrap(),
@ -113,7 +105,7 @@ impl InputFile {
Ok(Self { Ok(Self {
path: filename.as_ref().to_owned(), path: filename.as_ref().to_owned(),
file: f, file: f,
rc: Rc::new(RefCell::new(1)), rc: Arc::new(()),
}) })
} }
@ -147,7 +139,6 @@ impl InputFile {
/// Finds new files in the given directory, taking the last time we looked at this path as parameter. /// Finds new files in the given directory, taking the last time we looked at this path as parameter.
/// This method works recursively. /// This method works recursively.
/// If `last` is `None`, it'll load all file. /// If `last` is `None`, it'll load all file.
#[cfg(feature = "std")]
pub fn find_new_files_rec<P: AsRef<Path>>( pub fn find_new_files_rec<P: AsRef<Path>>(
dir: P, dir: P,
last_check: &Option<Duration>, last_check: &Option<Duration>,
@ -182,13 +173,9 @@ pub fn find_new_files_rec<P: AsRef<Path>>(
Ok(new_files) Ok(new_files)
} }
#[cfg(feature = "std")]
impl Drop for InputFile { impl Drop for InputFile {
fn drop(&mut self) { fn drop(&mut self) {
let mut rc = self.rc.borrow_mut(); if Arc::into_inner(core::mem::take(&mut self.rc)).is_some() {
assert_ne!(*rc, 0, "InputFile rc should never be 0");
*rc -= 1;
if *rc == 0 {
// try to remove the file, but ignore errors // try to remove the file, but ignore errors
drop(remove_file(&self.path)); drop(remove_file(&self.path));
} }