Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add heap corruption exception handling #85

Closed
wants to merge 2 commits into from

Conversation

h3r2tic
Copy link
Contributor

@h3r2tic h3r2tic commented Jun 8, 2024

Checklist

  • I have read the Contributor Guide
  • I have read and agree to the Code of Conduct
  • I have added a description of my changes and why I'd like them included in the section below

Description of Changes

We've been using crash-handler in Tiny Glade, and noticed a few quiet crashes, where our crash reporter had nothing to say. I suspect those are heap corruptions (in graphics drivers or DLLs that inject themselves into our app). Windows will not call the unhandled exception filter for those.

This PR adds a vectored exception handler that gets to act first. VEH is only used to process heap corruptions in this PR, allowing the unhandled exception filter to process the rest.

Disclaimer: I have no idea what I'm doing, but it catches an intentional heap corruption in my test. Here's the heap corruption code (source), for science of course:

unsafe fn corrupt_windows_heap() {
    use windows::core::PCSTR;
    use windows::Win32::Foundation::BOOL;
    use windows::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA};
    use windows::Win32::System::Memory::{GetProcessHeap, HeapHandle};

    let kernel32 = LoadLibraryA(PCSTR("kernel32.dll\0".as_ptr().cast()));
    if let Ok(kernel32) = kernel32 {
        eprintln!("Corrupting the windows heap");

        let heap_free: Option<
            unsafe extern "system" fn(HeapHandle, u32, *const core::ffi::c_void) -> BOOL,
        > = std::mem::transmute(GetProcAddress(
            kernel32,
            PCSTR("HeapFree\0".as_ptr().cast()),
        ));

        if let Some(heap_free) = heap_free {
            let heap = GetProcessHeap().unwrap();
            let bad_pointer = 3 as *mut core::ffi::c_void;
            heap_free(heap, 0, bad_pointer);
            eprintln!("Oh no, the heap is still alive :o");
        }
    } else {
        eprintln!("Can't corrupt heap: failed to load kernel32");
    }
}
windows = { version = "0.37", features = [
    "Win32_Foundation",
    "Win32_System_LibraryLoader",
    "Win32_System_Memory"
] }

@h3r2tic h3r2tic requested a review from Jake-Shadle as a code owner June 8, 2024 00:34
@gabrielesvelto
Copy link
Contributor

gabrielesvelto commented Jun 8, 2024

FYI we've had an VEH catching STATUS_HEAP_CORRUPTION exceptions in Firefox for a while, but several times the handler itself hits another crash before being able to process it. You might want a Windows Error Reporting runtime exception module to catch those "the world is on fire" crashes instead. We have one (see this and this) but it requires building and installing a separate DLL (plus registry modifications) so it might not be suitable for all projects. On the upside it can also catch FAST_FAIL_* exceptions which cannot be caught with VEH/SEH.

@h3r2tic
Copy link
Contributor Author

h3r2tic commented Jun 8, 2024

Oooh, thanks for chiming in, @gabrielesvelto 💕 That's great to know for when we hear of silent crashes again 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants