Ignore:
Timestamp:
Apr 15, 2011, 2:47:32 AM (14 years ago)
Author:
dmik
Message:

kernel32/SEH: Fixed a couple of bugs in SEH processing that could cause a bunch of various crashes when unwinding the Win32 exception chain (usually at process termination, as a result of both a fatal exception or a clean exit).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/exceptions.cpp

    r21615 r21618  
    114114void KillWin32Process(void);
    115115
    116 static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec, PEXCEPTIONREGISTRATIONRECORD pERegRec, PCONTEXTRECORD pCtxRec, PVOID p, PSZ szTrapDump);
     116static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
     117                             PEXCEPTIONREGISTRATIONRECORD pERegRec,
     118                             PCONTEXTRECORD pCtxRec, PVOID p, PSZ szTrapDump);
     119
     120extern "C"
     121int __cdecl __seh_handler(PWINEXCEPTION_RECORD pRec,
     122                          PWINEXCEPTION_FRAME pFrame,
     123                          PCONTEXTRECORD pContext, PVOID pVoid);
     124
     125extern "C"
     126PWINEXCEPTION_FRAME __cdecl __seh_get_prev_frame(PWINEXCEPTION_FRAME pFrame);
    117127
    118128#ifdef DEBUG
    119 void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
     129static void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
    120130#else
    121131#define PrintWin32ExceptionChain(a)
     
    335345DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
    336346{
    337   PWINEXCEPTION_FRAME   pFrame, dispatch, nested_frame;
    338   int                   rc;
    339 
    340   // get chain of exception frames
    341   rc  = ExceptionContinueSearch;
    342 
    343   nested_frame = NULL;
    344   TEB *winteb = GetThreadTEB();
    345   pFrame      = (PWINEXCEPTION_FRAME)winteb->except;
    346 
    347   dprintf(("KERNEL32: RtlDispatchException entered"));
    348 
    349   PrintWin32ExceptionChain(pFrame);
    350 
    351   // walk the exception chain
    352   while( (pFrame != NULL) && ((ULONG)((ULONG)pFrame & 0xFFFFF000) != 0xFFFFF000) )
    353   {
    354         dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev));
    355         if (pFrame == pFrame->Prev) {
     347    PWINEXCEPTION_FRAME   pFrame, pPrevFrame, dispatch, nested_frame;
     348    int                   rc;
     349
     350    // get chain of exception frames
     351    rc  = ExceptionContinueSearch;
     352
     353    nested_frame = NULL;
     354    TEB *winteb = GetThreadTEB();
     355    pFrame      = (PWINEXCEPTION_FRAME)winteb->except;
     356
     357    dprintf(("KERNEL32: RtlDispatchException entered"));
     358
     359    PrintWin32ExceptionChain(pFrame);
     360
     361    // walk the exception chain
     362    while( (pFrame != NULL) && ((ULONG)((ULONG)pFrame & 0xFFFFF000) != 0xFFFFF000) )
     363    {
     364        pPrevFrame = __seh_get_prev_frame(pFrame);
     365
     366        dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X",
     367                 pFrame, pPrevFrame));
     368        if (pFrame == pPrevFrame) {
    356369            dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
    357370            return 0;
     
    374387
    375388        /* call handler */
    376         if(pFrame->Handler) {
    377             rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler );
    378         }
    379         else {
     389        if (pFrame->Handler)
     390        {
     391            rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch,
     392                                 pFrame->Handler, EXC_RaiseHandler);
     393        }
     394        else
     395        {
    380396            dprintf(("pFrame->Handler is NULL!!!!!"));
    381397            rc = ExceptionContinueSearch;
     
    395411        {
    396412        case ExceptionContinueExecution:
    397             if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) {
     413            if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE))
     414            {
    398415                dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
    399416                return rc;
     
    410427        }
    411428
    412         dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev));
    413         if (pFrame == pFrame->Prev) {
     429        dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X",
     430                 pFrame, pPrevFrame));
     431        if (pFrame == pPrevFrame)
     432        {
    414433            dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
    415434            break;
    416435        }
    417         pFrame = pFrame->Prev;
     436        pFrame = pPrevFrame;
    418437  }
    419438  dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
     
    442461                         DWORD es,  DWORD fs,   DWORD gs,  DWORD ss)
    443462{
    444   PWINEXCEPTION_FRAME frame, dispatch;
     463  PWINEXCEPTION_FRAME frame, prevFrame, dispatch;
    445464  WINEXCEPTION_RECORD record, newrec;
    446465  WINCONTEXT          context;
     
    492511  while (((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) && (frame != pEndFrame))
    493512  {
     513        prevFrame = __seh_get_prev_frame(frame);
     514
    494515        /* Check frame address */
    495516        if (pEndFrame && (frame > pEndFrame))
     
    499520            newrec.ExceptionRecord  = pRecord;
    500521            newrec.NumberParameters = 0;
    501             dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
     522            dprintf(("KERNEL32: RtlUnwind terminating thread (invalid target).\n"));
    502523            DosExit(EXIT_THREAD, 0);
    503524        }
     
    510531            newrec.ExceptionRecord  = pRecord;
    511532            newrec.NumberParameters = 0;
    512             dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
     533            dprintf(("KERNEL32: RtlUnwind terminating thread (bad stack).\n"));
    513534            DosExit(EXIT_THREAD, 0);
    514535        }
     
    540561            break;
    541562        }
    542         dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));
    543         SetExceptionChain((DWORD)frame->Prev);
    544         frame = frame->Prev;
     563        dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, prevFrame));
     564        SetExceptionChain((DWORD)prevFrame);
     565        frame = prevFrame;
    545566        dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame,
    546                  ((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) ? frame->Prev : (void*)0xFFFFFFFF));
     567                 ((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) ?
     568                 __seh_get_prev_frame(frame->Prev) : (void*)0xFFFFFFFF));
    547569  }
    548570
     
    12371259    case XCPT_PROCESS_TERMINATE:
    12381260    case XCPT_ASYNC_PROCESS_TERMINATE:
    1239 ////        dprintfException(pERepRec, pERegRec, pCtxRec, p);
     1261#if 0
     1262        dprintfException(pERepRec, pERegRec, pCtxRec, p);
     1263        PrintExceptionChain();
     1264#endif
    12401265        SetExceptionChain((ULONG)-1);
    12411266        goto continuesearch;
     
    18111836//*****************************************************************************
    18121837//*****************************************************************************
    1813 void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
    1814 {
    1815   dprintf(("Win32 exception chain:"));
    1816   while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
    1817         dprintf(("  Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
    1818         if (pframe == pframe->Prev) {
    1819             dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
    1820             break;
    1821         }
    1822         pframe = pframe->Prev;
    1823   }
    1824   dprintf(("END of Win32 exception chain."));
    1825 }
    1826 
    1827 #endif
    1828 
     1838void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pFrame)
     1839{
     1840    dprintf(("Win32 exception chain:"));
     1841    while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
     1842    {
     1843        PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame(pFrame);
     1844        dprintf(("  Record at %08X, Prev at %08X, handler at %08X%s",
     1845                 pFrame, pPrevFrame, pFrame->Handler,
     1846                 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ?
     1847                 " (SEH)" : ""));
     1848        if (pFrame == pPrevFrame)
     1849        {
     1850            dprintf(("Chain corrupted! Record at %08X pointing to itself!",
     1851                     pFrame));
     1852            break;
     1853        }
     1854        pFrame = pPrevFrame;
     1855    }
     1856    dprintf(("END of Win32 exception chain."));
     1857}
     1858#endif
    18291859
    18301860/*****************************************************************************
Note: See TracChangeset for help on using the changeset viewer.