Skip to content

Commit df15a2a

Browse files
committed
Auto merge of rust-lang#123490 - niluxv:strict_prov_unwind_seh, r=Amanieu
Refactor `panic_unwind/seh.rs` pointer use * `x86` now conforms to strict-provenance * `x86_64` now uses the expose API (instead of `as` casts) * changed `ptr_t` from a type alias to a `repr(transparent)` struct for some extra type-safety * replaced the `ptr!` macro by methods on `ptr_t`, as there is now no reason (as far as I can see) anymore to use a macro On `x86_64` pointers in SEH are represented by 32-bit offsets from `__ImageBase`, so we can't use a pointer type. It might be possible to leak the provenance into the FFI by using a `MaybeUninit<u32>` instead of a `u32`, but that is a bit more involved than using expose, and I'm not sure that would be worth it.
2 parents ebe1b73 + 59ee6ac commit df15a2a

File tree

2 files changed

+73
-41
lines changed

2 files changed

+73
-41
lines changed

panic_unwind/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#![feature(panic_unwind)]
2020
#![feature(staged_api)]
2121
#![feature(std_internals)]
22+
#![feature(strict_provenance)]
23+
#![feature(exposed_provenance)]
2224
#![feature(rustc_attrs)]
2325
#![panic_runtime]
2426
#![feature(panic_runtime)]

panic_unwind/src/seh.rs

+71-41
Original file line numberDiff line numberDiff line change
@@ -109,58 +109,88 @@ struct Exception {
109109
// [1]: https://www.geoffchappell.com/studies/msvc/language/predefined/
110110

111111
#[cfg(target_arch = "x86")]
112-
#[macro_use]
113112
mod imp {
114-
pub type ptr_t = *mut u8;
115-
116-
macro_rules! ptr {
117-
(0) => {
118-
core::ptr::null_mut()
119-
};
120-
($e:expr) => {
121-
$e as *mut u8
122-
};
113+
#[repr(transparent)]
114+
#[derive(Copy, Clone)]
115+
pub struct ptr_t(*mut u8);
116+
117+
impl ptr_t {
118+
pub const fn null() -> Self {
119+
Self(core::ptr::null_mut())
120+
}
121+
122+
pub const fn new(ptr: *mut u8) -> Self {
123+
Self(ptr)
124+
}
125+
126+
pub const fn raw(self) -> *mut u8 {
127+
self.0
128+
}
123129
}
124130
}
125131

126132
#[cfg(not(target_arch = "x86"))]
127-
#[macro_use]
128133
mod imp {
129-
pub type ptr_t = u32;
134+
use core::ptr::addr_of;
135+
136+
// On 64-bit systems, SEH represents pointers as 32-bit offsets from `__ImageBase`.
137+
#[repr(transparent)]
138+
#[derive(Copy, Clone)]
139+
pub struct ptr_t(u32);
130140

131141
extern "C" {
132142
pub static __ImageBase: u8;
133143
}
134144

135-
macro_rules! ptr {
136-
(0) => (0);
137-
($e:expr) => {
138-
(($e as usize) - (addr_of!(imp::__ImageBase) as usize)) as u32
145+
impl ptr_t {
146+
pub const fn null() -> Self {
147+
Self(0)
148+
}
149+
150+
pub fn new(ptr: *mut u8) -> Self {
151+
// We need to expose the provenance of the pointer because it is not carried by
152+
// the `u32`, while the FFI needs to have this provenance to excess our statics.
153+
//
154+
// NOTE(niluxv): we could use `MaybeUninit<u32>` instead to leak the provenance
155+
// into the FFI. In theory then the other side would need to do some processing
156+
// to get a pointer with correct provenance, but these system functions aren't
157+
// going to be cross-lang LTOed anyway. However, using expose is shorter and
158+
// requires less unsafe.
159+
let addr: usize = ptr.expose_provenance();
160+
let image_base = unsafe { addr_of!(__ImageBase) }.addr();
161+
let offset: usize = addr - image_base;
162+
Self(offset as u32)
163+
}
164+
165+
pub const fn raw(self) -> u32 {
166+
self.0
139167
}
140168
}
141169
}
142170

171+
use imp::ptr_t;
172+
143173
#[repr(C)]
144174
pub struct _ThrowInfo {
145175
pub attributes: c_uint,
146-
pub pmfnUnwind: imp::ptr_t,
147-
pub pForwardCompat: imp::ptr_t,
148-
pub pCatchableTypeArray: imp::ptr_t,
176+
pub pmfnUnwind: ptr_t,
177+
pub pForwardCompat: ptr_t,
178+
pub pCatchableTypeArray: ptr_t,
149179
}
150180

151181
#[repr(C)]
152182
pub struct _CatchableTypeArray {
153183
pub nCatchableTypes: c_int,
154-
pub arrayOfCatchableTypes: [imp::ptr_t; 1],
184+
pub arrayOfCatchableTypes: [ptr_t; 1],
155185
}
156186

157187
#[repr(C)]
158188
pub struct _CatchableType {
159189
pub properties: c_uint,
160-
pub pType: imp::ptr_t,
190+
pub pType: ptr_t,
161191
pub thisDisplacement: _PMD,
162192
pub sizeOrOffset: c_int,
163-
pub copyFunction: imp::ptr_t,
193+
pub copyFunction: ptr_t,
164194
}
165195

166196
#[repr(C)]
@@ -186,20 +216,20 @@ const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
186216

187217
static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
188218
attributes: 0,
189-
pmfnUnwind: ptr!(0),
190-
pForwardCompat: ptr!(0),
191-
pCatchableTypeArray: ptr!(0),
219+
pmfnUnwind: ptr_t::null(),
220+
pForwardCompat: ptr_t::null(),
221+
pCatchableTypeArray: ptr_t::null(),
192222
};
193223

194224
static mut CATCHABLE_TYPE_ARRAY: _CatchableTypeArray =
195-
_CatchableTypeArray { nCatchableTypes: 1, arrayOfCatchableTypes: [ptr!(0)] };
225+
_CatchableTypeArray { nCatchableTypes: 1, arrayOfCatchableTypes: [ptr_t::null()] };
196226

197227
static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
198228
properties: 0,
199-
pType: ptr!(0),
229+
pType: ptr_t::null(),
200230
thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
201231
sizeOrOffset: mem::size_of::<Exception>() as c_int,
202-
copyFunction: ptr!(0),
232+
copyFunction: ptr_t::null(),
203233
};
204234

205235
extern "C" {
@@ -246,9 +276,9 @@ macro_rules! define_cleanup {
246276
super::__rust_drop_panic();
247277
}
248278
}
249-
unsafe extern $abi2 fn exception_copy(_dest: *mut Exception,
250-
_src: *mut Exception)
251-
-> *mut Exception {
279+
unsafe extern $abi2 fn exception_copy(
280+
_dest: *mut Exception, _src: *mut Exception
281+
) -> *mut Exception {
252282
panic!("Rust panics cannot be copied");
253283
}
254284
}
@@ -296,24 +326,24 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
296326
// In any case, we basically need to do something like this until we can
297327
// express more operations in statics (and we may never be able to).
298328
atomic_store_seqcst(
299-
addr_of_mut!(THROW_INFO.pmfnUnwind) as *mut u32,
300-
ptr!(exception_cleanup) as u32,
329+
addr_of_mut!(THROW_INFO.pmfnUnwind).cast(),
330+
ptr_t::new(exception_cleanup as *mut u8).raw(),
301331
);
302332
atomic_store_seqcst(
303-
addr_of_mut!(THROW_INFO.pCatchableTypeArray) as *mut u32,
304-
ptr!(addr_of!(CATCHABLE_TYPE_ARRAY)) as u32,
333+
addr_of_mut!(THROW_INFO.pCatchableTypeArray).cast(),
334+
ptr_t::new(addr_of_mut!(CATCHABLE_TYPE_ARRAY).cast()).raw(),
305335
);
306336
atomic_store_seqcst(
307-
addr_of_mut!(CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]) as *mut u32,
308-
ptr!(addr_of!(CATCHABLE_TYPE)) as u32,
337+
addr_of_mut!(CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]).cast(),
338+
ptr_t::new(addr_of_mut!(CATCHABLE_TYPE).cast()).raw(),
309339
);
310340
atomic_store_seqcst(
311-
addr_of_mut!(CATCHABLE_TYPE.pType) as *mut u32,
312-
ptr!(addr_of!(TYPE_DESCRIPTOR)) as u32,
341+
addr_of_mut!(CATCHABLE_TYPE.pType).cast(),
342+
ptr_t::new(addr_of_mut!(TYPE_DESCRIPTOR).cast()).raw(),
313343
);
314344
atomic_store_seqcst(
315-
addr_of_mut!(CATCHABLE_TYPE.copyFunction) as *mut u32,
316-
ptr!(exception_copy) as u32,
345+
addr_of_mut!(CATCHABLE_TYPE.copyFunction).cast(),
346+
ptr_t::new(exception_copy as *mut u8).raw(),
317347
);
318348

319349
extern "system-unwind" {

0 commit comments

Comments
 (0)