From e06b77eead1cd53ac9ddab72e27b6c0d9f81edb7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 25 Sep 2025 15:31:32 -0700 Subject: [PATCH 1/2] GetCurrentProcess only once --- src/backtrace/win32.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backtrace/win32.rs b/src/backtrace/win32.rs index 9c459306..7ee063db 100644 --- a/src/backtrace/win32.rs +++ b/src/backtrace/win32.rs @@ -112,8 +112,6 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { let function_table_access = dbghelp.SymFunctionTableAccess64(); let get_module_base = dbghelp.SymGetModuleBase64(); - let process_handle = GetCurrentProcess(); - // Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64` // since it's in theory supported on more systems. match (*dbghelp.dbghelp()).StackWalkEx() { @@ -146,7 +144,8 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { 0, ) == TRUE { - frame.inner.base_address = get_module_base(process_handle, frame.ip() as _) as _; + frame.inner.base_address = + unsafe { get_module_base(process, frame.ip() as _) as _ }; if !cb(&frame) { break; @@ -178,7 +177,8 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { None, ) == TRUE { - frame.inner.base_address = get_module_base(process_handle, frame.ip() as _) as _; + frame.inner.base_address = + unsafe { get_module_base(process, frame.ip() as _) as _ }; if !cb(&frame) { break; From d4738ccff79e4f8158c3e69e8b926174519c2a27 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 25 Sep 2025 15:32:04 -0700 Subject: [PATCH 2/2] deny(unsafe_op_in_unsafe_fn) in backtrace/win32.rs --- src/backtrace/win32.rs | 70 +++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/backtrace/win32.rs b/src/backtrace/win32.rs index 7ee063db..4029609f 100644 --- a/src/backtrace/win32.rs +++ b/src/backtrace/win32.rs @@ -8,6 +8,7 @@ //! //! Note that all dbghelp support is loaded dynamically, see `src/dbghelp.rs` //! for more information about that. +#![deny(unsafe_op_in_unsafe_fn)] use super::super::{dbghelp, windows_sys::*}; use core::ffi::c_void; @@ -97,11 +98,12 @@ struct MyContext(CONTEXT); #[inline(always)] pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { // Allocate necessary structures for doing the stack walk - let process = GetCurrentProcess(); - let thread = GetCurrentThread(); + let process = unsafe { GetCurrentProcess() }; + let thread = unsafe { GetCurrentThread() }; - let mut context = mem::zeroed::(); - RtlCaptureContext(&mut context.0); + // This is a classic C-style out-ptr struct. Zero it to start. + let mut context = unsafe { mem::zeroed::() }; + unsafe { RtlCaptureContext(&mut context.0) }; // Ensure this process's symbols are initialized let dbghelp = match dbghelp::init() { @@ -114,10 +116,11 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { // Attempt to use `StackWalkEx` if we can, but fall back to `StackWalk64` // since it's in theory supported on more systems. - match (*dbghelp.dbghelp()).StackWalkEx() { + match unsafe { (*dbghelp.dbghelp()).StackWalkEx() } { #[allow(non_snake_case)] Some(StackWalkEx) => { - let mut inner: STACKFRAME_EX = mem::zeroed(); + // This is a classic C-style out-ptr struct. Zero it to start. + let mut inner: STACKFRAME_EX = unsafe { mem::zeroed() }; inner.StackFrameSize = mem::size_of::() as u32; let mut frame = super::Frame { inner: Frame { @@ -131,19 +134,20 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { _ => unreachable!(), }; - while StackWalkEx( - image as u32, - process, - thread, - frame_ptr, - &mut context.0 as *mut CONTEXT as *mut _, - None, - Some(function_table_access), - Some(get_module_base), - None, - 0, - ) == TRUE - { + while unsafe { + StackWalkEx( + image as u32, + process, + thread, + frame_ptr, + &mut context.0 as *mut CONTEXT as *mut _, + None, + Some(function_table_access), + Some(get_module_base), + None, + 0, + ) == TRUE + } { frame.inner.base_address = unsafe { get_module_base(process, frame.ip() as _) as _ }; @@ -155,7 +159,8 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { None => { let mut frame = super::Frame { inner: Frame { - stack_frame: StackFrame::Old(mem::zeroed()), + // This is a classic C-style out-ptr struct. Zero it to start. + stack_frame: StackFrame::Old(unsafe { mem::zeroed() }), base_address: 0 as _, }, }; @@ -165,18 +170,19 @@ pub unsafe fn trace(cb: &mut dyn FnMut(&super::Frame) -> bool) { _ => unreachable!(), }; - while dbghelp.StackWalk64()( - image as u32, - process, - thread, - frame_ptr, - &mut context.0 as *mut CONTEXT as *mut _, - None, - Some(function_table_access), - Some(get_module_base), - None, - ) == TRUE - { + while unsafe { + dbghelp.StackWalk64()( + image as u32, + process, + thread, + frame_ptr, + &mut context.0 as *mut CONTEXT as *mut _, + None, + Some(function_table_access), + Some(get_module_base), + None, + ) == TRUE + } { frame.inner.base_address = unsafe { get_module_base(process, frame.ip() as _) as _ };