Skip to content

Commit 26ef682

Browse files
authored
mimalloc: prevent crashes in the post-command hook handling (v2.52 version) (#834)
Similar to 1475d9f (mimalloc: use "weak" random seed when statically linked, 2023-05-12) (which was actually already applied upstream in microsoft/mimalloc@3e1d800e (potential fix for windows static linking with thread creation in dll's, 2022-11-07), this ensures that another code path uses "weak" random seeds when initializing mimalloc. The scenario when this happens is likely the exact same as back when the original fix was implemented (but I can only hypothesize about this, as I was unable to find a reproducer in my setup, and even the reporters could not find a reliable reproducer, either): an `atexit()` handler is called after mimalloc's own `atexit()` handler deinitializes mimalloc. This `atexit()` handler (namely `post_command_hook_atexit()`) then calls `getenv()`, which internally resolves to `mingw_getenv()`, which wants to `calloc()` the result so that it is not overwritten while in use. This, in turn, uses mimalloc, which dutifully initializes the random seed. It apparently takes a different code path than back in 2023, though, where it now tries to initialize a strong random generator implemented in bcrypt.dll. However, that initialization fails because it happens during the phase when only `atexit()` handlers are called, and bcrypt has obviously already been deinitialized, in a way that causes a crash. The stack trace in question looks like this: ``` ntdll!ZwWaitForMultipleObjects+0x140 ... KERNELBASE!WaitForMultipleObjectsEx+0x123 ... KERNELBASE!WaitForMultipleObjects+0x11 ... kernel32!WerpReportFaultInternal+0x62c ... kernel32!WerpReportFault+0xc5 ... KERNELBASE!UnhandledExceptionFilter+0x34c ... ntdll!RtlpThreadExceptionFilter+0x2e ... ntdll!RtlUserThreadStart$filt$0+0x3f0 ... ntdll!_C_specific_handler+0x93 ... ntdll!RtlpExecuteHandlerForException+0xf ... ntdll!RtlDispatchException+0x437 ... ntdll!KiUserExceptionDispatch+0x2e() ... bcryptPrimitives!AesRNGState_generate+0x79 ... bcryptPrimitives!GenRandomAes+0xf70 ... bcryptPrimitives!MSCryptGenRandom+0x15f ... bcrypt!BCryptGenRandom+0x7a ... bcrypt!BCryptGenSysternPreferredRandom+0x340 .... bcrypt!BCryptGenRandom+0x119 ... git!_mi_prim_random_buf+0x23() [compat\mimalloc\prim\windows\prim.c @ 648] git!mi_random_init_ex+0x61() [compat\mimalloc\random.c @ 179] git!_mi_heap_init+0xe8() [compat\mimalloc\heap.c @ 226] git!mi_thread_init+0x21b() [compat\mimalloc\init.c @ 396] git!mi_heap_get_default+0x9() [compat\mimalloc\mimalloc\prim.h @ 415] git!_mi_malloc_generic+0x9d() [compat\mimalloc\page.c @ 993] git!mingw_getenv+0x4f() [compat\mingw.c @ 2446] git!run_post_command_hook+0x84() [git.c @ 515] ``` Let's treat this code path in the exact same way as the code path in `mi_heap_main_init()`.
2 parents 0142f7a + 99b6e73 commit 26ef682

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

compat/mimalloc/heap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,11 @@ void _mi_heap_init(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool
223223
heap->no_reclaim = noreclaim;
224224
heap->tag = tag;
225225
if (heap == tld->heap_backing) {
226+
#if defined(_WIN32) && !defined(MI_SHARED_LIB)
227+
_mi_random_init_weak(&heap->random); // prevent allocation failure during bcrypt dll initialization with static linking
228+
#else
226229
_mi_random_init(&heap->random);
230+
#endif
227231
}
228232
else {
229233
_mi_random_split(&tld->heap_backing->random, &heap->random);

0 commit comments

Comments
 (0)