Source linked

244 Recursive Exception Frames Revealed a Phantom DLL in Windows

devblogs.microsoft.com@systems_wire2 hours ago·Systems Engineering·2 comments

A stack overflow crash traced to shell32.dll's destruction order-Raymond Chen dissects the recursive exception death spiral that exposed a DLL not truly unloaded.

microsoftraymond chenold new thingshell32stack overflowwindows debugging

244 recursive exception dispatch frames stacked on a single thread—that’s the smoking gun Raymond Chen’s team found when debugging a third-party program crashing with a stack overflow. The crash dumps pointed at shell32.dll as the culprit, but the real root lay deeper in the DLL’s destruction sequence.

The Recursive Death Spiral

Every crash dump showed the same repeating pattern: RtlLookupFunctionEntryRtlDispatchExceptionKiUserExceptionDispatch, over and over. An exception occurred in kernel mode, was reflected back to user mode for handling, but while the system tried to locate the right exception handler, another exception fired, restarting the loop. That cycle ate the stack until the process died from a stack overflow exception.

Chen walked the stack back to the origin. The first exception originated at combase!CoTaskMemFree, called from within shell32!wil::details::string_maker::~string_maker during process shutdown. The chain: shell32!dllmain_crt_process_detachshell32!dllmain_dispatchntdll!LdrShutdownProcess. The DLL was being formally unloaded via FreeLibrary, but something in its DllMain DLL_PROCESS_DETACH handler went sideways.

Unraveling the Stack

The repeating block of frames stopped at the source of the first fault. Chen used the exception record passed to RtlDispatchException to inspect the original problem. The context record at the KiUserExceptionDispatch frame held the details: a memory access violation inside CoTaskMemFree while cleaning up a string in shell32’s destructor. That violation triggered another exception, which triggered another, creating the death spiral.

What the bug report didn’t say initially was that the DLL was not truly unloaded from memory despite FreeLibrary being called. The crash happened because the DLL’s memory was still referenced after its reference count hit zero but before the kernel fully removed it. The next post in the series will cover how that phantom state occurs—and how to prevent it.


Source: DLL that was not present in memory despite not being formally unloaded
Domain: devblogs.microsoft.com

Read original source ->

External source stays available while the OJO article and comment thread stay local.

Comments load interactively on the live page.