From 4af215362bdf2d9a4dfe68c3a2834b8f77007bd4 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 3 Jun 2026 11:39:58 +0200 Subject: [PATCH 1/2] test: trigger crashes with correct WER exception codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For stack-buffer-overruns, the example uses `RaiseFailFastException` as appropriate, but for fastfails, it used `__fastfail(77)` that made WER deliver `STATUS_STACK_BUFFER_OVERRUN (0xC0000409)`. - `__fastfail(77)` → `kernel int 0x29` → WER always normalizes to `STATUS_STACK_BUFFER_OVERRUN (0xC0000409)` https://learn.microsoft.com/en-us/cpp/intrinsics/fastfail vs. - `RaiseFailFastException(NULL, NULL, 0)` → WER preserves the original exception code `(STATUS_FAIL_FAST_EXCEPTION = 0xC0000602)` https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-raisefailfastexception --- examples/example.c | 6 +++--- src/backends/native/sentry_wer.c | 8 ++++++++ tests/test_integration_native.py | 12 +++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/examples/example.c b/examples/example.c index d3a083280..25200de27 100644 --- a/examples/example.c +++ b/examples/example.c @@ -416,9 +416,9 @@ trigger_stack_buffer_overrun() static void trigger_fastfail_crash() { - // this bypasses WINDOWS SEH and will only be caught with the crashpad WER - // module enabled - __fastfail(77); + // this bypasses WINDOWS SEH and will only be caught with the + // crashpad/native WER module enabled + RaiseFailFastException(NULL, NULL, 0); } #endif diff --git a/src/backends/native/sentry_wer.c b/src/backends/native/sentry_wer.c index 37542528c..3657543a4 100644 --- a/src/backends/native/sentry_wer.c +++ b/src/backends/native/sentry_wer.c @@ -146,6 +146,14 @@ process_wer_exception( ctx->platform.threads[0].thread_id = ctx->crashed_tid; ctx->platform.threads[0].context = exception_info->context; + char buf[4096]; + snprintf(buf, sizeof(buf), + "### SENTRY_WER: crashed_pid=%lu crashed_tid=%llu " + "exception_code=0x%08X", + (unsigned long)ctx->crashed_pid, + (unsigned long long)ctx->crashed_tid, ctx->platform.exception_code); + OutputDebugStringA(buf); + InterlockedExchange(&ctx->state, SENTRY_CRASH_STATE_CRASHED); if (SetEvent(event)) { claimed = TRUE; diff --git a/tests/test_integration_native.py b/tests/test_integration_native.py index 3132aa4f5..54180014b 100644 --- a/tests/test_integration_native.py +++ b/tests/test_integration_native.py @@ -88,8 +88,14 @@ def test_native_capture_crash(cmake, httpserver): reason="WER crash tests are only available in MSVC Windows builds", ) @pytest.mark.with_wer -@pytest.mark.parametrize("crash_arg", ["fastfail", "stack-buffer-overrun"]) -def test_native_wer(cmake, httpserver, crash_arg): +@pytest.mark.parametrize( + "crash_arg,exception_code", + [ + pytest.param("fastfail", 0xC0000602, id="fastfail"), + pytest.param("stack-buffer-overrun", 0xC0000409, id="stack-buffer-overrun"), + ], +) +def test_native_wer_crash(cmake, httpserver, crash_arg, exception_code): """Test WER crash capture with native backend""" tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "native"}) @@ -106,7 +112,7 @@ def test_native_wer(cmake, httpserver, crash_arg): assert len(httpserver.log) >= 1 envelope = Envelope.deserialize(httpserver.log[0][0].get_data()) - assert_native_crash(envelope, exception_code=0xC0000409) + assert_native_crash(envelope, exception_code=exception_code) @pytest.mark.skipif(not has_oom, reason="OOM test unreliable in this environment") From af1795f9b9cc3cefcecb613dc6575ce60619a668 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 3 Jun 2026 12:06:59 +0200 Subject: [PATCH 2/2] clean up debug output --- src/backends/native/sentry_wer.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/backends/native/sentry_wer.c b/src/backends/native/sentry_wer.c index 3657543a4..37542528c 100644 --- a/src/backends/native/sentry_wer.c +++ b/src/backends/native/sentry_wer.c @@ -146,14 +146,6 @@ process_wer_exception( ctx->platform.threads[0].thread_id = ctx->crashed_tid; ctx->platform.threads[0].context = exception_info->context; - char buf[4096]; - snprintf(buf, sizeof(buf), - "### SENTRY_WER: crashed_pid=%lu crashed_tid=%llu " - "exception_code=0x%08X", - (unsigned long)ctx->crashed_pid, - (unsigned long long)ctx->crashed_tid, ctx->platform.exception_code); - OutputDebugStringA(buf); - InterlockedExchange(&ctx->state, SENTRY_CRASH_STATE_CRASHED); if (SetEvent(event)) { claimed = TRUE;