From 620f56d7894fa46fc78cc17b1bc8450a4cc2997f Mon Sep 17 00:00:00 2001 From: janzert Date: Fri, 4 Sep 2026 03:50:56 -0400 Subject: [PATCH] Fix the signature scanner writing to a freed stack frame `scan_iter` zero-initialises a `Buffer` as a local, takes a `&mut [u8]` over it via `slice::from_raw_parts_mut`, and moves that slice into the `iter::from_fn` closure it returns. Only the slice is moved: the buffer itself remains a local of `scan_iter`, so by the time the returned iterator is first polled the storage the slice points at has been given back, and every poll reads and writes roughly 4 KiB of a dead stack frame. Move the buffer into the closure and take the slice inside each call, where its storage is live for as long as the pointer is used. Co-Authored-By: Claude Opus 5 --- src/signature.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/signature.rs b/src/signature.rs index ba48e3a..32c0b3e 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -262,13 +262,21 @@ impl Signature { // SAFETY: zero-initializing an array of u8 poses no problems in terms of memory safety let mut buffer = unsafe { mem::zeroed::>() }; - // SAFETY: As the data is zero-initialized, we know it's safe to reinterpret this data as - // an array uf u8. - let buffer = unsafe { - slice::from_raw_parts_mut(&mut buffer as *mut _ as *mut u8, size_of::>()) - }; - iter::from_fn(move || { + // The slice has to be created here, inside the closure, rather than + // once before the iterator is built. The buffer is owned by the + // closure, so its storage is live for as long as the iterator is, + // but outside the closure `&mut buffer` names a local of + // `scan_iter`, whose frame is already gone by the time the iterator + // is first polled. + // + // SAFETY: As the data is zero-initialized, we know it's safe to + // reinterpret this data as an array uf u8. The buffer it points at + // is live for the whole of this call. + let buffer = unsafe { + slice::from_raw_parts_mut(&mut buffer as *mut _ as *mut u8, size_of::>()) + }; + if addr.value() >= overall_end { return None; }