Crash Dump Analysis Patterns (Part 86)

Sometimes we suspect one component but there is another, Nested Offender, that raised an exception. That exception propagated through exception filters and handlers and prompted the suspected component to respond with a diagnostic message. Here is an example of the thread showing the runtime error message box:

The corresponding stack trace points to MathMLMimer module:

0:087> kL
ChildEBP RetAddr 
5546ddf0 76f50dde ntdll!KiFastSystemCallRet
5546ddf4 76f3b0b2 user32!NtUserWaitMessage+0xc
5546de28 76f3bcda user32!DialogBox2+0x202
5546de50 76f8ccdc user32!InternalDialogBox+0xd0
5546def0 76f8d25e user32!SoftModalMessageBox+0x69f
5546e040 76f8d394 user32!MessageBoxWorker+0x2c7
5546e098 76f8d43e user32!MessageBoxTimeoutW+0x7f
5546e0cc 76f8d5ec user32!MessageBoxTimeoutA+0xa1
5546e0ec 6f245ac7 user32!MessageBoxExA+0x1b
5546e10c 76f8d65e ieframe!Detour_MessageBoxExA+0x2c
5546e128 0c841c28 user32!MessageBoxA+0×45
WARNING: Stack unwind information not available. Following frames may be wrong.
5546e16c 0c83d1b9 MathMLMimer!DllUnregisterServer+0×9437
5546e190 0c83cf72 MathMLMimer!DllUnregisterServer+0×49c8
00000000 00000000 MathMLMimer!DllUnregisterServer+0×4781

0:087> .asm no_code_bytes
Assembly options: no_code_bytes

0:087> ub 0c841c28
MathMLMimer!DllUnregisterServer+0×941d:
0c841c0e push    dword ptr [ebp+10h]
0c841c11 push    dword ptr [ebp+0Ch]
0c841c14 push    dword ptr [ebp+8]
0c841c17 push    dword ptr [ebp-4]
0c841c1a push    dword ptr [MathMLMimer!DllUnregisterServer+0×135ab (0c84bd9c)]
0c841c20 call    MathMLMimer!DllUnregisterServer+0×4aab (0c83d29c)
0c841c25 pop     ecx
0c841c26 call    eax

However, when looking at raw stack data, we see exception processing residue that points to ComponentA that tried to allocate more memory than was available (bad_alloc C++ exception):

0:087> !teb
TEB at 7ff84000
    ExceptionList:        5546e4e8
    StackBase:            55470000
    StackLimit:           55457000

    SubSystemTib:         00000000
    FiberData:            00001e00
    ArbitraryUserPointer: 00000000
    Self:                 7ff84000
    EnvironmentPointer:   00000000
    ClientId:             0000136c . 00001714
    RpcHandle:            00000000
    Tls Storage:          5826eef0
    PEB Address:          7ffd7000
    LastErrorValue:       0
    LastStatusValue:      0
    Count Owned Locks:    0
    HardErrorMode:        0

0:087> dds 55457000 55470000
55457000  00000000
[...]
5546e694  55470000
5546e698  55457000
5546e69c  00274cb0
5546e6a0  5546e9f4
5546e6a4  772899f7 ntdll!KiUserExceptionDispatcher+0xf
5546e6a8  0046e6b8
5546e6ac  5546e6d8
5546e6b0  5546e6b8
[…]

0:087> .cxr 5546e6d8
eax=5546e9a4 ebx=00001000 ecx=00000003 edx=00000000 esi=689a9c54 edi=6b330000
eip=771942eb esp=5546e9a4 ebp=5546e9f4 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00240212
kernel32!RaiseException+0×58:
771942eb c9              leave

0:087> .exr 5546e6b8
ExceptionAddress: 771942eb (kernel32!RaiseException+0×00000058)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 3
   Parameter[0]: 19930520
   Parameter[1]: 5546ea3c
   Parameter[2]: 688b7954
  pExceptionObject: 5546ea3c
  _s_ThrowInfo    : 688b7954
  Type            : class std::bad_alloc
  Type            : class std::exception

0:087> kL
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr 
5546e9f4 6882dead kernel32!RaiseException+0×58
WARNING: Stack unwind information not available. Following frames may be wrong.
5546ea2c 6882a59d ComponentA!DllUnregisterServer+0×1adbe0
5546ea48 6868157b ComponentA!DllUnregisterServer+0×1aa2d0
5546ea74 6869d2c6 ComponentA!DllUnregisterServer+0×12ae
5546ea88 6868a415 ComponentA!DllUnregisterServer+0×1cff9
5546eaa0 685a165e ComponentA!DllUnregisterServer+0xa148
5546eac8 685a9828 ComponentA+0×5165e
5546ebc8 68605fdd ComponentA+0×59828
5546ebf0 6a807aba ComponentA+0xb5fdd
5546ec08 6a807a77 mshtml!CViewDispClient::Invalidate+0×59
5546ec20 00000000 mshtml!CDispRoot::InvalidateRoot+0×1d

0:087> ub 6882dead
ComponentA!DllUnregisterServer+0×1adbc4:
6882de91 je      ComponentA!DllUnregisterServer+0×1adbcd (6882de9a)
6882de93 mov     dword ptr [ebp-0Ch],1994000h
6882de9a lea     eax,[ebp-0Ch]
6882de9d push    eax
6882de9e push    dword ptr [ebp-10h]
6882dea1 push    dword ptr [ebp-1Ch]
6882dea4 push    dword ptr [ebp-20h]
6882dea7 call    dword ptr [ComponentA!DllUnregisterServer+0×1ba0a3 (6883a370)]

It happens that MathMLMimer has an exception filter that shows the runtime error:

0:087> !exchain
5546e4e8: MathMLMimer!DllUnregisterServer+18df (0c83a0d0)
5546e578: kernel32!_except_handler4+0 (7715e289)
5546e5e4: ntdll!ExecuteHandler2+3a (77289bad)
5546faa8: user32!_except_handler4+0 (76f951ba)
5546fb0c: user32!_except_handler4+0 (76f951ba)
5546fbd0: ntdll!_except_handler4+0 (77239834)
Invalid exception stack at ffffffff

Notice the mystical 6882dead return address above. This is just a coincidence, I believe.

Nested Offender is different from Nested Exception pattern. The latter is about an exception handler that experiences or throws another exception.

- Dmitry Vostokov @ DumpAnalysis.org -

2 Responses to “Crash Dump Analysis Patterns (Part 86)”

  1. Crash Dump Analysis » Blog Archive » Stack trace collection, message box, hidden exception, nested offender, insufficient memory, C++ exception, heap leak and ubiquitous component: pattern cooperation Says:

    […] a thread blocked by a message box, find another hidden exception and from it see the real nested offender that experienced insufficient memory condition resulted in C++ exception. You can see WinDbg […]

  2. Crash Dump Analysis » Blog Archive » Old Mental Dumps from June 24th Says:

    […] Crash Dump Analysis Patterns (Part 86) - Nested Offender pattern. Appears also in the following case study: Stack trace collection, […]

Leave a Reply

You must be logged in to post a comment.