Skip to content

Commit b7544c6

Browse files
committed
More
1 parent 074d9b2 commit b7544c6

File tree

5 files changed

+138
-127
lines changed

5 files changed

+138
-127
lines changed

crash-context/src/linux/getcontext.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Implementation of [`getcontext`](https://man7.org/linux/man-pages/man3/getcontext.3.html)
22
3-
extern "C" {
3+
unsafe extern "C" {
44
/// A portable implementation of [`getcontext`](https://man7.org/linux/man-pages/man3/getcontext.3.html)
55
/// since it is not supported by all libc implementations, namely `musl`, as
66
/// it has been deprecated from POSIX for over a decade

crash-context/src/mac/ipc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use mach2::{
2020
pub use mach2::{kern_return::kern_return_t, message::mach_msg_return_t};
2121
use std::{ffi::CStr, time::Duration};
2222

23-
extern "C" {
23+
unsafe extern "C" {
2424
/// From `<usr/include/mach/mach_traps.h>`, there is no binding for this in mach2
2525
pub fn pid_for_task(task: port::mach_port_name_t, pid: *mut i32) -> kern_return_t;
2626
}

crash-handler/src/unix/pthread_interpose.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct PthreadCreateParams {
2929
static mut THREAD_DESTRUCTOR_KEY: libc::pthread_key_t = 0;
3030

3131
#[cfg(all(target_env = "musl", not(miri)))]
32-
extern "C" {
32+
unsafe extern "C" {
3333
/// This is the weak alias for `pthread_create`. We declare this so we can
3434
/// use its address when targeting musl, as we can't lookup the actual
3535
/// `pthread_create` symbol at runtime since we've interposed it.

sadness-generator/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ authors = [
77
"Embark <[email protected]>",
88
"Jake Shadle <[email protected]>",
99
]
10-
edition = "2021"
10+
edition = "2024"
1111
license = "MIT OR Apache-2.0"
1212
documentation = "https://docs.rs/sadness-generator"
1313
homepage = "https://github.com/EmbarkStudios/crash-handling/tree/main/sadness-generator"
@@ -16,7 +16,7 @@ homepage = "https://github.com/EmbarkStudios/crash-handling/tree/main/sadness-ge
1616
categories = ["simulation"]
1717
keywords = ["crash", "sadness", "signal", "exception"]
1818
# We use `asm!` and rawdylib Windows bindings
19-
rust-version = "1.71.0"
19+
rust-version = "1.85.0"
2020

2121
[dependencies]
2222
libc.workspace = true

sadness-generator/src/lib.rs

Lines changed: 133 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -69,40 +69,42 @@ impl SadnessFlavor {
6969
///
7070
/// This is not safe. It intentionally crashes.
7171
pub unsafe fn make_sad(self) -> ! {
72-
match self {
73-
Self::Abort => raise_abort(),
74-
Self::Segfault => raise_segfault(),
75-
Self::DivideByZero => raise_floating_point_exception(),
76-
Self::Illegal => raise_illegal_instruction(),
77-
#[cfg(unix)]
78-
Self::Bus => raise_bus(),
79-
Self::Trap => raise_trap(),
80-
#[allow(unused_variables)]
81-
Self::StackOverflow {
82-
non_rust_thread,
83-
long_jumps,
84-
} => {
85-
if !non_rust_thread {
86-
raise_stack_overflow()
87-
} else {
88-
#[cfg(unix)]
89-
{
90-
raise_stack_overflow_in_non_rust_thread(long_jumps)
91-
}
92-
#[cfg(windows)]
93-
{
72+
unsafe {
73+
match self {
74+
Self::Abort => raise_abort(),
75+
Self::Segfault => raise_segfault(),
76+
Self::DivideByZero => raise_floating_point_exception(),
77+
Self::Illegal => raise_illegal_instruction(),
78+
#[cfg(unix)]
79+
Self::Bus => raise_bus(),
80+
Self::Trap => raise_trap(),
81+
#[allow(unused_variables)]
82+
Self::StackOverflow {
83+
non_rust_thread,
84+
long_jumps,
85+
} => {
86+
if !non_rust_thread {
9487
raise_stack_overflow()
88+
} else {
89+
#[cfg(unix)]
90+
{
91+
raise_stack_overflow_in_non_rust_thread(long_jumps)
92+
}
93+
#[cfg(windows)]
94+
{
95+
raise_stack_overflow()
96+
}
9597
}
9698
}
99+
#[cfg(windows)]
100+
Self::Purecall => raise_purecall(),
101+
#[cfg(windows)]
102+
Self::InvalidParameter => raise_invalid_parameter(),
103+
#[cfg(windows)]
104+
Self::HeapCorruption => raise_heap_corruption(),
105+
#[cfg(target_os = "macos")]
106+
Self::Guard => raise_guard_exception(),
97107
}
98-
#[cfg(windows)]
99-
Self::Purecall => raise_purecall(),
100-
#[cfg(windows)]
101-
Self::InvalidParameter => raise_invalid_parameter(),
102-
#[cfg(windows)]
103-
Self::HeapCorruption => raise_heap_corruption(),
104-
#[cfg(target_os = "macos")]
105-
Self::Guard => raise_guard_exception(),
106108
}
107109
}
108110
}
@@ -113,7 +115,7 @@ impl SadnessFlavor {
113115
///
114116
/// This is not safe. It intentionally emits `SIGABRT`.
115117
pub unsafe fn raise_abort() -> ! {
116-
libc::abort()
118+
unsafe { libc::abort() }
117119
}
118120

119121
/// This is the fixed address used to generate a segfault. It's possible that
@@ -131,7 +133,7 @@ pub const SEGFAULT_ADDRESS: u32 = 0x42;
131133
/// This is not safe. It intentionally crashes.
132134
pub unsafe fn raise_segfault() -> ! {
133135
let bad_ptr: *mut u8 = SEGFAULT_ADDRESS as _;
134-
std::ptr::write_volatile(bad_ptr, 1);
136+
unsafe { std::ptr::write_volatile(bad_ptr, 1) };
135137

136138
// If we actually get here that means the address is mapped and writable
137139
// by the current process which is...unexpected
@@ -144,7 +146,7 @@ pub unsafe fn raise_segfault() -> ! {
144146
///
145147
/// This is not safe. It intentionally crashes.
146148
pub unsafe fn raise_floating_point_exception() -> ! {
147-
let ohno = {
149+
let ohno = unsafe {
148150
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
149151
{
150152
let mut divisor: u32;
@@ -177,10 +179,12 @@ pub unsafe fn raise_floating_point_exception() -> ! {
177179
///
178180
/// This is not safe. It intentionally crashes.
179181
pub unsafe fn raise_illegal_instruction() -> ! {
180-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
181-
asm!("ud2");
182-
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
183-
asm!("udf #0");
182+
unsafe {
183+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
184+
asm!("ud2");
185+
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
186+
asm!("udf #0");
187+
}
184188

185189
std::process::abort()
186190
}
@@ -195,35 +199,37 @@ pub unsafe fn raise_bus() -> ! {
195199
let mut temp_name = [0; 14];
196200
temp_name.copy_from_slice(b"sigbus.XXXXXX\0");
197201

198-
let bus_fd = libc::mkstemp(temp_name.as_mut_ptr().cast());
199-
assert!(bus_fd != -1);
200-
201-
let page_size = libc::sysconf(libc::_SC_PAGESIZE) as usize;
202-
203-
let mapping = std::slice::from_raw_parts_mut(
204-
libc::mmap(
205-
std::ptr::null_mut(),
206-
128,
207-
libc::PROT_READ | libc::PROT_WRITE,
208-
libc::MAP_SHARED,
209-
bus_fd,
210-
0,
211-
)
212-
.cast::<u8>(),
213-
page_size + page_size / 2,
214-
);
215-
216-
libc::unlink(temp_name.as_ptr().cast());
202+
unsafe {
203+
let bus_fd = libc::mkstemp(temp_name.as_mut_ptr().cast());
204+
assert!(bus_fd != -1);
205+
206+
let page_size = libc::sysconf(libc::_SC_PAGESIZE) as usize;
207+
208+
let mapping = std::slice::from_raw_parts_mut(
209+
libc::mmap(
210+
std::ptr::null_mut(),
211+
128,
212+
libc::PROT_READ | libc::PROT_WRITE,
213+
libc::MAP_SHARED,
214+
bus_fd,
215+
0,
216+
)
217+
.cast::<u8>(),
218+
page_size + page_size / 2,
219+
);
217220

218-
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
219-
// The system shall always zero-fill any partial page at the end of
220-
// an object. Further, the system shall never write out any modified
221-
// portions of the last page of an object which are beyond its end.
222-
// References within the address range starting at pa and continuing
223-
// for len bytes to whole pages following the end of an object shall
224-
// result in delivery of a SIGBUS signal.
225-
mapping[20] = 20;
226-
println!("{}", mapping[20]);
221+
libc::unlink(temp_name.as_ptr().cast());
222+
223+
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
224+
// The system shall always zero-fill any partial page at the end of
225+
// an object. Further, the system shall never write out any modified
226+
// portions of the last page of an object which are beyond its end.
227+
// References within the address range starting at pa and continuing
228+
// for len bytes to whole pages following the end of an object shall
229+
// result in delivery of a SIGBUS signal.
230+
mapping[20] = 20;
231+
println!("{}", mapping[20]);
232+
}
227233

228234
std::process::abort()
229235
}
@@ -234,12 +240,14 @@ pub unsafe fn raise_bus() -> ! {
234240
///
235241
/// This is not safe. It intentionally crashes.
236242
pub unsafe fn raise_trap() -> ! {
237-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
238-
asm!("int3");
239-
#[cfg(target_arch = "arm")]
240-
asm!(".inst 0xe7f001f0");
241-
#[cfg(target_arch = "aarch64")]
242-
asm!(".inst 0xd4200000");
243+
unsafe {
244+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
245+
asm!("int3");
246+
#[cfg(target_arch = "arm")]
247+
asm!(".inst 0xe7f001f0");
248+
#[cfg(target_arch = "aarch64")]
249+
asm!(".inst 0xd4200000");
250+
}
243251

244252
std::process::abort()
245253
}
@@ -281,68 +289,71 @@ pub unsafe fn raise_stack_overflow() -> ! {
281289
/// This is not safe. It intentionally crashes.
282290
#[cfg(unix)]
283291
pub unsafe fn raise_stack_overflow_in_non_rust_thread(uses_longjmp: bool) -> ! {
284-
let mut native: libc::pthread_t = std::mem::zeroed();
285-
let mut attr: libc::pthread_attr_t = std::mem::zeroed();
286-
287-
assert_eq!(
288-
libc::pthread_attr_setstacksize(&mut attr, 2 * 1024 * 1024),
289-
0,
290-
"failed to set thread stack size",
291-
);
292+
unsafe {
293+
let mut native: libc::pthread_t = std::mem::zeroed();
294+
let mut attr: libc::pthread_attr_t = std::mem::zeroed();
292295

293-
use std::sync;
296+
assert_eq!(
297+
libc::pthread_attr_setstacksize(&mut attr, 2 * 1024 * 1024),
298+
0,
299+
"failed to set thread stack size",
300+
);
294301

295-
let pair = sync::Arc::new((sync::Mutex::new(false), sync::Condvar::new()));
296-
let tpair = pair.clone();
302+
use std::sync;
297303

298-
extern "C" fn thread_start(arg: *mut libc::c_void) -> *mut libc::c_void {
299-
{
300-
let tpair =
301-
unsafe { sync::Arc::from_raw(arg as *const (sync::Mutex<bool>, sync::Condvar)) };
302-
let (lock, cvar) = &*tpair;
303-
let mut started = lock.lock().unwrap();
304-
*started = true;
305-
cvar.notify_one();
306-
}
304+
let pair = sync::Arc::new((sync::Mutex::new(false), sync::Condvar::new()));
305+
let tpair = pair.clone();
307306

308-
unsafe { raise_stack_overflow() };
309-
}
307+
extern "C" fn thread_start(arg: *mut libc::c_void) -> *mut libc::c_void {
308+
{
309+
let tpair = unsafe {
310+
sync::Arc::from_raw(arg as *const (sync::Mutex<bool>, sync::Condvar))
311+
};
312+
let (lock, cvar) = &*tpair;
313+
let mut started = lock.lock().unwrap();
314+
*started = true;
315+
cvar.notify_one();
316+
}
310317

311-
let ret = libc::pthread_create(
312-
&mut native,
313-
&attr,
314-
thread_start,
315-
sync::Arc::into_raw(tpair) as *mut _,
316-
);
318+
unsafe { raise_stack_overflow() };
319+
}
317320

318-
// We might not get here, but that's ok
319-
assert_eq!(
320-
libc::pthread_attr_destroy(&mut attr),
321-
0,
322-
"failed to destroy thread attributes"
323-
);
324-
assert_eq!(ret, 0, "pthread_create failed");
321+
let ret = libc::pthread_create(
322+
&mut native,
323+
&attr,
324+
thread_start,
325+
sync::Arc::into_raw(tpair) as *mut _,
326+
);
325327

326-
// Note if we're doing longjmp shenanigans, we can't do thread join, that
327-
// has to be handled by the calling code
328-
if !uses_longjmp {
328+
// We might not get here, but that's ok
329329
assert_eq!(
330-
libc::pthread_join(native, std::ptr::null_mut()),
330+
libc::pthread_attr_destroy(&mut attr),
331331
0,
332-
"failed to join"
332+
"failed to destroy thread attributes"
333333
);
334-
}
334+
assert_eq!(ret, 0, "pthread_create failed");
335+
336+
// Note if we're doing longjmp shenanigans, we can't do thread join, that
337+
// has to be handled by the calling code
338+
if !uses_longjmp {
339+
assert_eq!(
340+
libc::pthread_join(native, std::ptr::null_mut()),
341+
0,
342+
"failed to join"
343+
);
344+
}
335345

336-
let (lock, cvar) = &*pair;
337-
let mut started = lock.lock().unwrap();
338-
while !*started {
339-
started = cvar.wait(started).unwrap();
340-
}
346+
let (lock, cvar) = &*pair;
347+
let mut started = lock.lock().unwrap();
348+
while !*started {
349+
started = cvar.wait(started).unwrap();
350+
}
341351

342-
std::thread::sleep(std::time::Duration::from_millis(10));
352+
std::thread::sleep(std::time::Duration::from_millis(10));
343353

344-
#[allow(clippy::empty_loop)]
345-
loop {}
354+
#[allow(clippy::empty_loop)]
355+
loop {}
356+
}
346357
}
347358

348359
/// [`SadnessFlavor::StackOverflow`]
@@ -353,7 +364,7 @@ pub unsafe fn raise_stack_overflow_in_non_rust_thread(uses_longjmp: bool) -> ! {
353364
#[inline]
354365
#[cfg(unix)]
355366
pub unsafe fn raise_stack_overflow_in_non_rust_thread_normal() -> ! {
356-
raise_stack_overflow_in_non_rust_thread(false)
367+
unsafe { raise_stack_overflow_in_non_rust_thread(false) }
357368
}
358369

359370
/// [`SadnessFlavor::StackOverflow`]
@@ -364,7 +375,7 @@ pub unsafe fn raise_stack_overflow_in_non_rust_thread_normal() -> ! {
364375
#[inline]
365376
#[cfg(unix)]
366377
pub unsafe fn raise_stack_overflow_in_non_rust_thread_longjmp() -> ! {
367-
raise_stack_overflow_in_non_rust_thread(true)
378+
unsafe { raise_stack_overflow_in_non_rust_thread(true) }
368379
}
369380

370381
/// [`SadnessFlavor::Purecall`]

0 commit comments

Comments
 (0)