From 48f89ee56e164efd64ab06e55c1a374a948d3cec Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 25 May 2026 15:21:12 +0200 Subject: [PATCH 1/2] fix: clear g_options before freeing options --- src/sentry_core.c | 2 +- tests/unit/test_basic.c | 29 +++++++++++++++++++++++++++++ tests/unit/tests.inc | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/sentry_core.c b/src/sentry_core.c index 3019f7884..bd8f0a5e6 100644 --- a/src/sentry_core.c +++ b/src/sentry_core.c @@ -341,12 +341,12 @@ sentry_close(void) || !options->backend->can_capture_after_shutdown)) { sentry__run_clean(options->run, false); } + g_options = NULL; sentry_options_free(options); } else { SENTRY_WARN("sentry_close() called, but options was empty"); } - g_options = NULL; sentry__mutex_unlock(&g_options_lock); sentry__scope_cleanup(); diff --git a/tests/unit/test_basic.c b/tests/unit/test_basic.c index b8915d1af..9fa06b747 100644 --- a/tests/unit/test_basic.c +++ b/tests/unit/test_basic.c @@ -1,3 +1,5 @@ +#include "sentry_alloc.h" +#include "sentry_backend.h" #include "sentry_core.h" #include "sentry_database.h" #include "sentry_options.h" @@ -425,3 +427,30 @@ SENTRY_TEST(installation_id) sentry_free(id_a); } + +static void +backend_free_options_ref(sentry_backend_t *backend) +{ + const sentry_options_t **options_ref = backend->data; + *options_ref = sentry__options_getref(); +} + +SENTRY_TEST(clear_options) +{ + const sentry_options_t *options_ref = NULL; + + SENTRY_TEST_OPTIONS_NEW(options); + + sentry_backend_t *backend = SENTRY_MAKE(sentry_backend_t); + TEST_ASSERT(!!backend); + backend->free_func = backend_free_options_ref; + backend->data = &options_ref; + sentry_options_set_backend(options, backend); + + sentry_init(options); + sentry_close(); + + // The backend free hook runs from sentry_options_free(). At that point, + // sentry__options_getref() must no longer expose the options. + TEST_CHECK(options_ref == NULL); +} diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index b1a224831..f47a04467 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -76,6 +76,7 @@ XX(capture_minidump_without_sentry_init) XX(check_version) XX(child_spans) XX(child_spans_ts) +XX(clear_options) XX(client_report_concurrent) XX(client_report_discard) XX(client_report_discard_envelope) From c8f204fcb3830ad46b0f8c2b1ac2beee18368b05 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 25 May 2026 16:13:08 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c79f5b03..4ea158a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Native/macOS: fix thread stack descriptor. ([#1726](https://github.com/getsentry/sentry-native/pull/1726)) - Cap rate-limit retry-after values at 24 hours to prevent a MITM-provided response from disabling event delivery for the process lifetime. ([#1744](https://github.com/getsentry/sentry-native/pull/1744)) - Native: validate ELF header entry sizes. ([#1746](https://github.com/getsentry/sentry-native/pull/1746)) +- Fix a shutdown-time use-after-free window in `sentry_close()`. ([#1750](https://github.com/getsentry/sentry-native/pull/1750)) ## 0.14.2