From 71050e2752ffa0f09fee88fa3a758a8443b3ac7a Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 26 Aug 2014 21:35:21 +0000 Subject: [PATCH] [PSEH3] - Do not try to dereference potentially invalid pointers. The FrameRegister->ExceptionPointers pointer is only valid in the context of the filter function. Indeed, the PSEH3 exception handler allocates it on the stack, and when control gets back to the __excep { } coder, ebp and esp were already restored to their original values, so whatever can happen to those pointers. Investigation and debugging mastered by Thomas Faber, whose efforts were shamelessly stolen by me to improve my commit statistics. CORE-8469 #comment patch committed, you may want to commit your testcase though :-p svn path=/trunk/; revision=63958 --- reactos/include/reactos/libs/pseh/pseh3.h | 9 ++++++--- reactos/lib/pseh/i386/pseh3.c | 14 ++++++++------ reactos/lib/pseh/i386/pseh3_asmdef.h | 13 +++++++------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/reactos/include/reactos/libs/pseh/pseh3.h b/reactos/include/reactos/libs/pseh/pseh3.h index fee3b63fa8b..457d7d93a27 100644 --- a/reactos/include/reactos/libs/pseh/pseh3.h +++ b/reactos/include/reactos/libs/pseh/pseh3.h @@ -64,6 +64,9 @@ typedef struct _SEH3$_REGISTRATION_FRAME /* Except handler stores pointer to exception pointers here */ PSEH3$_EXCEPTION_POINTERS volatile ExceptionPointers; + /* Except handle stores the exception code here */ + unsigned long ExceptionCode; + /* Registers that we need to save */ unsigned long Esp; unsigned long Ebp; @@ -252,14 +255,14 @@ _SEH3$_AutoCleanup( /* Since we cannot use nested functions, we declare these globally as macros */ #define _abnormal_termination() (_SEH3$_TrylevelFrame.ExceptionPointers != 0) -#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode) +#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionCode) #define _exception_info() (_SEH3$_TrylevelFrame.ExceptionPointers) #else /* __cplusplus || __clang__ */ #define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \ inline __attribute__((always_inline, gnu_inline)) \ - unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; } + unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; } /* On GCC the filter function is a nested function with __fastcall calling convention. The eax register contains a base address the function uses @@ -284,7 +287,7 @@ _SEH3$_AutoCleanup( _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wshadow\"") \ inline __attribute__((always_inline, gnu_inline)) \ - unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; } \ + unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; } \ inline __attribute__((always_inline, gnu_inline)) \ void * _exception_info() { return _SEH3$_TrylevelFrame.ExceptionPointers; } \ _Pragma("GCC diagnostic pop") \ diff --git a/reactos/lib/pseh/i386/pseh3.c b/reactos/lib/pseh/i386/pseh3.c index 9f2041528aa..8a3be57e03f 100644 --- a/reactos/lib/pseh/i386/pseh3.c +++ b/reactos/lib/pseh/i386/pseh3.c @@ -197,8 +197,8 @@ _SEH3$_JumpToTarget( { asm volatile ( /* Load the registers */ - "movl 20(%%ecx), %%esp\n\t" - "movl 24(%%ecx), %%ebp\n\t" + "movl 24(%%ecx), %%esp\n\t" + "movl 28(%%ecx), %%ebp\n\t" /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */ "addl $4, %%esp\n\t" @@ -215,8 +215,8 @@ _SEH3$_JumpToTarget( { asm volatile ( /* Load the registers */ - "movl 20(%%ecx), %%esp\n\t" - "movl 24(%%ecx), %%ebp\n\t" + "movl 24(%%ecx), %%esp\n\t" + "movl 28(%%ecx), %%ebp\n\t" /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */ "addl $4, %%esp\n\t" @@ -274,8 +274,9 @@ _SEH3$_except_handler( /* Check if we have an exception handler */ if (CurrentFrame->ScopeTable->Target != NULL) { - /* Set exception pointers for this frame */ + /* Set exception pointers and code for this frame */ CurrentFrame->ExceptionPointers = &ExceptionPointers; + CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode; /* Get the filter result */ FilterResult = _SEH3$_GetFilterResult(CurrentFrame); @@ -316,8 +317,9 @@ _SEH3$_except_handler( /* Check if this is an unwind frame */ if (CurrentFrame->ScopeTable->Target == NULL) { - /* Set exception pointers for this frame */ + /* Set exception pointers and code for this frame */ CurrentFrame->ExceptionPointers = &ExceptionPointers; + CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode; /* Call the finally function */ _SEH3$_CallFinally(CurrentFrame); diff --git a/reactos/lib/pseh/i386/pseh3_asmdef.h b/reactos/lib/pseh/i386/pseh3_asmdef.h index 87d126fa8ca..74f7c83ff9a 100644 --- a/reactos/lib/pseh/i386/pseh3_asmdef.h +++ b/reactos/lib/pseh/i386/pseh3_asmdef.h @@ -5,12 +5,13 @@ #define SEH3_REGISTRATION_FRAME_EndOfChain 8 #define SEH3_REGISTRATION_FRAME_ScopeTable 12 #define SEH3_REGISTRATION_FRAME_ExceptionPointers 16 -#define SEH3_REGISTRATION_FRAME_Esp 20 -#define SEH3_REGISTRATION_FRAME_Ebp 24 -#define SEH3_REGISTRATION_FRAME_AllocaFrame 28 -#define SEH3_REGISTRATION_FRAME_Ebx 32 -#define SEH3_REGISTRATION_FRAME_Esi 36 -#define SEH3_REGISTRATION_FRAME_Edi 40 +#define SEH3_REGISTRATION_FRAME_ExceptionCode 20 +#define SEH3_REGISTRATION_FRAME_Esp 24 +#define SEH3_REGISTRATION_FRAME_Ebp 28 +#define SEH3_REGISTRATION_FRAME_AllocaFrame 32 +#define SEH3_REGISTRATION_FRAME_Ebx 36 +#define SEH3_REGISTRATION_FRAME_Esi 40 +#define SEH3_REGISTRATION_FRAME_Edi 44 #define SEH3_SCOPE_TABLE_Target 0 #define SEH3_SCOPE_TABLE_Filter 4 -- 2.17.1