Skip to content

Commit 77c69e4

Browse files
wan9chicodex
andcommitted
fix(fspy): prevent recursive access handling
Co-authored-by: GPT-5 Codex <codex@openai.com>
1 parent bee8aa0 commit 77c69e4

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

  • crates/fspy_preload_unix/src/client

crates/fspy_preload_unix/src/client/mod.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ pub mod convert;
22
pub mod raw_exec;
33

44
use std::{
5-
ffi::OsStr, fmt::Debug, num::NonZeroUsize, os::unix::ffi::OsStrExt as _, path::Path,
6-
sync::OnceLock,
5+
cell::Cell, ffi::OsStr, fmt::Debug, num::NonZeroUsize, os::unix::ffi::OsStrExt as _,
6+
path::Path, sync::OnceLock,
77
};
88

99
use convert::{ToAbsolutePath, ToAccessMode};
@@ -125,15 +125,37 @@ impl Client {
125125

126126
static CLIENT: OnceLock<Client> = OnceLock::new();
127127

128+
// Resolving and reporting a file access can call another interposed function.
129+
// Suppress same-thread re-entry to prevent recursive access handling while
130+
// still recording accesses from other threads.
131+
thread_local! {
132+
static HANDLING_OPEN: Cell<bool> = const { Cell::new(false) };
133+
}
134+
135+
struct ResetHandling<'a>(&'a Cell<bool>);
136+
impl Drop for ResetHandling<'_> {
137+
fn drop(&mut self) {
138+
self.0.set(false);
139+
}
140+
}
141+
128142
pub fn global_client() -> Option<&'static Client> {
129143
CLIENT.get()
130144
}
131145

132146
pub unsafe fn handle_open(path: impl ToAbsolutePath, mode: impl ToAccessMode) {
133-
if let Some(client) = global_client() {
134-
// SAFETY: path and mode contain valid pointers/values forwarded from the interposed function's caller
135-
unsafe { client.try_handle_open(path, mode) }.unwrap();
136-
}
147+
HANDLING_OPEN.with(|handling| {
148+
if handling.replace(true) {
149+
return;
150+
}
151+
152+
let _reset = ResetHandling(handling);
153+
154+
if let Some(client) = global_client() {
155+
// SAFETY: path and mode contain valid pointers/values forwarded from the interposed function's caller
156+
unsafe { client.try_handle_open(path, mode) }.unwrap();
157+
}
158+
});
137159
}
138160

139161
#[cfg(not(test))]

0 commit comments

Comments
 (0)