Przeglądaj źródła

* i386-win32 setjmp and longjmp: if SEH support is enabled, save/restore head of exception registration chain. Without this, a longjmp out of a function with exception frame(s) will leave these exception frames below ESP, which will fail integrity checks in OS and cause process termination if an exception occurs later on (or they may be overwritten by subsequent operations on stack and, again, cause undesired results).
* Additionally, use a branchless sequence to fix up result of longjmp.

git-svn-id: trunk@26238 -

sergei 11 lat temu
rodzic
commit
74f9d719f1
2 zmienionych plików z 13 dodań i 4 usunięć
  1. 10 4
      rtl/i386/setjump.inc
  2. 3 0
      rtl/i386/setjumph.inc

+ 10 - 4
rtl/i386/setjump.inc

@@ -23,6 +23,10 @@ asm
   movl %edi,Jmp_buf.sp(%eax)
   movl %edi,Jmp_buf.sp(%eax)
   movl (%esp),%edi
   movl (%esp),%edi
   movl %edi,Jmp_buf.pc(%eax)
   movl %edi,Jmp_buf.pc(%eax)
+{$ifdef FPC_USE_WIN32_SEH}
+  movl %fs:(0),%edi
+  movl %edi,Jmp_buf.exhead(%eax)
+{$endif FPC_USE_WIN32_SEH}
   movl Jmp_buf.edi(%eax),%edi
   movl Jmp_buf.edi(%eax),%edi
   xorl %eax,%eax
   xorl %eax,%eax
 end;
 end;
@@ -31,10 +35,12 @@ end;
 Procedure fpc_longJmp (Var S : Jmp_buf; value : longint); assembler;nostackframe;[Public, alias : 'FPC_LONGJMP']; compilerproc;
 Procedure fpc_longJmp (Var S : Jmp_buf; value : longint); assembler;nostackframe;[Public, alias : 'FPC_LONGJMP']; compilerproc;
 asm
 asm
   xchgl %edx,%eax
   xchgl %edx,%eax
-  testl %eax,%eax
-  jnz   .L1
-  incl  %eax
-.L1:
+  cmpl  $1,%eax
+  adcl  $0,%eax                  // if result<1 then inc(result) -- never return zero.
+{$ifdef FPC_USE_WIN32_SEH}
+  movl  Jmp_buf.exhead(%edx),%edi
+  movl  %edi,%fs:(0)
+{$endif FPC_USE_WIN32_SEH}
   movl Jmp_buf.ebx(%edx),%ebx
   movl Jmp_buf.ebx(%edx),%ebx
   movl Jmp_buf.esi(%edx),%esi
   movl Jmp_buf.esi(%edx),%esi
   movl Jmp_buf.edi(%edx),%edi
   movl Jmp_buf.edi(%edx),%edi

+ 3 - 0
rtl/i386/setjumph.inc

@@ -17,6 +17,9 @@ Type
   jmp_buf = packed record
   jmp_buf = packed record
     ebx,esi,edi : Longint;
     ebx,esi,edi : Longint;
     bp,sp,pc : Pointer;
     bp,sp,pc : Pointer;
+{$ifdef FPC_USE_WIN32_SEH}
+    exhead: Pointer;
+{$endif FPC_USE_WIN32_SEH}
     end;
     end;
   PJmp_buf = ^jmp_buf;
   PJmp_buf = ^jmp_buf;