Skip to content

Commit

Permalink
Raise noncontinuable exception when aborting on earlier Windows versions
Browse files Browse the repository at this point in the history
  • Loading branch information
nxtn committed Sep 2, 2020
1 parent e88e908 commit 060a3a4
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 48 deletions.
35 changes: 35 additions & 0 deletions library/panic_abort/src/c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#![allow(nonstandard_style)]

use libc::{c_int, c_ulong, c_void};

pub type DWORD = c_ulong;
pub type BOOL = c_int;

pub type LPVOID = *mut c_void;

pub const FALSE: BOOL = 0;

pub const PF_FASTFAIL_AVAILABLE: DWORD = 23;

pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;

#[repr(C)]
pub struct EXCEPTION_RECORD {
pub ExceptionCode: DWORD,
pub ExceptionFlags: DWORD,
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ExceptionAddress: LPVOID,
pub NumberParameters: DWORD,
pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS],
}

pub enum CONTEXT {}

extern "system" {
pub fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL;
pub fn RaiseFailFastException(
pExceptionRecord: *const EXCEPTION_RECORD,
pContextRecord: *const CONTEXT,
dwFlags: DWORD,
);
}
50 changes: 30 additions & 20 deletions library/panic_abort/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@

use core::any::Any;

cfg_if::cfg_if! {
if #[cfg(windows)] {
use core::ptr;
mod c;
}
}

#[rustc_std_internal_symbol]
#[allow(improper_ctypes_definitions)]
pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
Expand Down Expand Up @@ -48,28 +55,31 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
__rust_abort();
}
} else if #[cfg(windows)] {
// On Windows, use the processor-specific __fastfail mechanism. In Windows 8
// and later, this will terminate the process immediately without running any
// in-process exception handlers. In earlier versions of Windows, this
// sequence of instructions will be treated as an access violation,
// terminating the process but without necessarily bypassing all exception
// handlers.
//
// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
//
// Note: this is the same implementation as in libstd's `abort_internal`
/// On Windows 8 and later versions, use the processor-specific `__fastfail`
/// mechanism. This will terminate the process immediately without running any
/// in-process exception handlers.
/// On Windows 7, use `RaiseFailFastException` to raise a noncontinuable exception
/// `STATUS_FAIL_FAST_EXCEPTION`.
/// On earlier versions of Windows, use `RaiseException` to raise the same
/// noncontinuable exception.
///
/// This is the same implementation as in libstd's `abort_internal`.
unsafe fn abort() -> ! {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
} else {
core::intrinsics::abort();
if c::IsProcessorFeaturePresent(c::PF_FASTFAIL_AVAILABLE) != c::FALSE {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
} else {
core::intrinsics::abort();
}
}
} else {
c::RaiseFailFastException(ptr::null(), ptr::null(), 0);
}
core::intrinsics::unreachable();
}
Expand Down
46 changes: 33 additions & 13 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;

pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008;

pub const PF_FASTFAIL_AVAILABLE: DWORD = 23;

pub const STATUS_FAIL_FAST_EXCEPTION: DWORD = 0xC0000602;

pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1;

#[repr(C)]
#[cfg(not(target_pointer_width = "64"))]
pub struct WSADATA {
Expand Down Expand Up @@ -625,24 +631,25 @@ pub struct timeval {
pub tv_usec: c_long,
}

pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;

#[repr(C)]
pub struct EXCEPTION_RECORD {
pub ExceptionCode: DWORD,
pub ExceptionFlags: DWORD,
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ExceptionAddress: LPVOID,
pub NumberParameters: DWORD,
pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS],
}

pub enum CONTEXT {}

// Functions forbidden when targeting UWP
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;

#[repr(C)]
pub struct EXCEPTION_RECORD {
pub ExceptionCode: DWORD,
pub ExceptionFlags: DWORD,
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ExceptionAddress: LPVOID,
pub NumberParameters: DWORD,
pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
}

pub enum CONTEXT {}

#[repr(C)]
pub struct EXCEPTION_POINTERS {
Expand Down Expand Up @@ -1027,6 +1034,19 @@ extern "system" {
pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;

pub fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL;
pub fn RaiseException(
dwExceptionCode: DWORD,
dwExceptionFlags: DWORD,
nNumberOfArguments: DWORD,
lpArguments: *const ULONG_PTR,
);
pub fn RaiseFailFastException(
pExceptionRecord: *const EXCEPTION_RECORD,
pContextRecord: *const CONTEXT,
dwFlags: DWORD,
);
}

// Functions that aren't available on every version of Windows that we support,
Expand Down
46 changes: 31 additions & 15 deletions library/std/src/sys/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,26 +300,42 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
.unwrap_or(c::INFINITE)
}

/// Use `__fastfail` to abort the process
/// On Windows 8 and later versions, use the processor-specific `__fastfail`
/// mechanism. This will terminate the process immediately without running any
/// in-process exception handlers.
/// On Windows 7, use `RaiseFailFastException` to raise a noncontinuable exception
/// `STATUS_FAIL_FAST_EXCEPTION`.
/// On earlier versions of Windows, use `RaiseException` to raise the same
/// noncontinuable exception.
///
/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
/// that function for more information on `__fastfail`
/// This is the same implementation as in libpanic_abort's `__rust_start_panic`.
#[allow(unreachable_code)]
pub fn abort_internal() -> ! {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
unsafe {
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
if c::IsProcessorFeaturePresent(c::PF_FASTFAIL_AVAILABLE) != c::FALSE {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
} else {
crate::intrinsics::abort();
}
}
} else {
match compat::lookup("kernel32", "RaiseFailFastException") {
Some(..) => c::RaiseFailFastException(ptr::null(), ptr::null(), 0),
None => c::RaiseException(
c::STATUS_FAIL_FAST_EXCEPTION,
c::EXCEPTION_NONCONTINUABLE,
0,
ptr::null(),
),
};
}
crate::intrinsics::unreachable();
}
crate::intrinsics::abort();
}

0 comments on commit 060a3a4

Please sign in to comment.