From a64f6b43ac693ab981bfd18b862ff65236ca04b3 Mon Sep 17 00:00:00 2001
From: Martin Stjernholm <mast@lysator.liu.se>
Date: Fri, 12 Jan 2001 00:28:30 +0100
Subject: [PATCH] Fixed proper error recovery in the RECUR opcodes where the
 pike_frame is changed destructively.

Test case: The following program should loop infinitely and not segfault
when the stack is eaten (running with -d necessary).

int main()
{
  int i = 5;
  catch(main());
  return main() + i;
}

Rev: src/interpret.c:1.180
Rev: src/interpret_functions.h:1.38
Rev: src/interpreter.h:1.54
---
 src/interpret.c           |  14 +++++-
 src/interpret_functions.h | 101 +++++++++++---------------------------
 src/interpreter.h         |   4 +-
 3 files changed, 43 insertions(+), 76 deletions(-)

diff --git a/src/interpret.c b/src/interpret.c
index ddff98c3e8..4da7768bbb 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.179 2001/01/10 19:56:37 mast Exp $");
+RCSID("$Id: interpret.c,v 1.180 2001/01/11 23:28:30 mast Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -754,6 +754,18 @@ void dump_backlog(void)
 #endif
 static int o_catch(unsigned char *pc);
 
+struct light_frame_info
+{
+  struct svalue *expendible;
+  struct svalue *locals;
+};
+
+static void restore_light_frame_info(struct light_frame_info *info)
+{
+  Pike_fp->expendible = info->expendible;
+  Pike_fp->locals = info->locals;
+}
+
 #ifdef PIKE_DEBUG
 #define EVAL_INSTR_RET_CHECK(x)						\
   if (x == -2)								\
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 23fa38d494..1f621d17f1 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -1,5 +1,5 @@
 /*
- * $Id: interpret_functions.h,v 1.37 2001/01/10 19:56:37 mast Exp $
+ * $Id: interpret_functions.h,v 1.38 2001/01/11 23:28:30 mast Exp $
  *
  * Opcode definitions for the interpreter.
  */
@@ -1485,19 +1485,42 @@ BREAK;
 
 
 /* Assume that the number of arguments is correct */
-OPCODE0_JUMP(F_RECUR,"recur")
+OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded")
+{
+  /* FIXME:
+   * this test should actually test if this function is
+   * overloaded or not. Currently it only tests if
+   * this context is inherited or not.
+   */
+  if(Pike_fp->current_object->prog != Pike_fp->context.prog)
+  {
+    apply_low(Pike_fp->current_object,
+	      arg1+Pike_fp->context.identifier_level,
+	      DO_NOT_WARN(Pike_sp - *--Pike_mark_sp));
+    pc+=sizeof(INT32);
+    DONE;
+  }
+}
+/* FALL THROUGH */
+
+/* Assume that the number of arguments is correct */
+OPCODE0_TAILJUMP(F_RECUR,"recur")
 {
   int x;
   INT32 num_locals, args;
   char *addr;
-  struct svalue *expendible=Pike_fp->expendible;
-  struct svalue *locals=Pike_fp->locals;
+  struct light_frame_info info;
   struct svalue *save_sp, **save_mark_sp;
+  ONERROR uwp;
 
   fast_check_threads_etc(6);
   check_c_stack(8192);
   check_stack(256);
 
+  info.expendible = Pike_fp->expendible;
+  info.locals = Pike_fp->locals;
+  SET_ONERROR(uwp, restore_light_frame_info, &info);
+
   save_sp = Pike_fp->expendible = Pike_fp->locals = *--Pike_mark_sp;
   args = DO_NOT_WARN(Pike_sp - Pike_fp->locals);
   save_mark_sp = Pike_mark_sp;
@@ -1528,8 +1551,7 @@ OPCODE0_JUMP(F_RECUR,"recur")
     assign_svalue(save_sp,Pike_sp-1);
     pop_n_elems(Pike_sp-save_sp-1);
   }
-  Pike_fp->expendible=expendible;
-  Pike_fp->locals=locals;
+  CALL_AND_UNSET_ONERROR(uwp);
   print_return_value();
 #ifdef PIKE_DEBUG
   if(Pike_sp != save_sp+1)
@@ -1538,73 +1560,6 @@ OPCODE0_JUMP(F_RECUR,"recur")
 }
 BREAK
 
-/* Assume that the number of arguments is correct */
-OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded")
-{
-  int x;
-  INT32 num_locals,args;
-  char *addr;
-
-  struct svalue *expendible=Pike_fp->expendible;
-  struct svalue *locals=Pike_fp->locals;
-  struct svalue *save_sp, **save_mark_sp;
-
-  /* FIXME:
-   * this test should actually test if this function is
-   * overloaded or not. Currently it only tests if
-   * this context is inherited or not.
-   */
-  if(Pike_fp->current_object->prog != Pike_fp->context.prog)
-  {
-    apply_low(Pike_fp->current_object,
-	      arg1+Pike_fp->context.identifier_level,
-	      DO_NOT_WARN(Pike_sp - *--Pike_mark_sp));
-    pc+=sizeof(INT32);
-  }else{
-    fast_check_threads_etc(6);
-    check_c_stack(8192);
-    check_stack(256);
-    
-    save_sp = Pike_fp->expendible = Pike_fp->locals = *--Pike_mark_sp;
-    args = DO_NOT_WARN(Pike_sp - Pike_fp->locals);
-    save_mark_sp = Pike_mark_sp;
-    
-    addr=pc+EXTRACT_INT(pc);
-    num_locals=EXTRACT_UCHAR(addr-2);
-    
-#ifdef PIKE_DEBUG
-    if(args != EXTRACT_UCHAR(addr-1))
-      fatal("Wrong number of arguments in F_RECUR %d!=%d\n",args,EXTRACT_UCHAR(addr-1));
-#endif
-    
-    clear_svalues(Pike_sp, num_locals - args);
-    Pike_sp += num_locals - args;
-    
-    x=eval_instruction(addr);
-    EVAL_INSTR_RET_CHECK(x);
-#ifdef PIKE_DEBUG
-  if(Pike_mark_sp < save_mark_sp)
-    fatal("mark Pike_sp underflow in F_RECUR.\n");
-#endif
-    Pike_mark_sp=save_mark_sp;
-    if(x>=0) mega_apply(APPLY_STACK, x, 0,0);
-    pc+=sizeof(INT32);
-    if(save_sp+1 < Pike_sp)
-    {
-      assign_svalue(save_sp,Pike_sp-1);
-      pop_n_elems(Pike_sp-save_sp-1);
-    }
-    Pike_fp->expendible=expendible;
-    Pike_fp->locals=locals;
-    print_return_value();
-#ifdef PIKE_DEBUG
-    if(Pike_sp != save_sp+1)
-      fatal("Stack whack in F_RECUR Pike_sp=%p, expected=%p\n",Pike_sp,save_sp+1);
-#endif
-  }
-}
-BREAK
-
 /* Assume that the number of arguments is correct */
 /* FIXME: adjust Pike_mark_sp */
 OPCODE0_JUMP(F_TAIL_RECUR,"tail recursion")
diff --git a/src/interpreter.h b/src/interpreter.h
index cc48afe492..f3bf32eb6a 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -194,9 +194,9 @@ static int eval_instruction(unsigned char *pc)
 #define OPCODE2_TAILJUMP(OP,DESC) } CASE(OP) {; 
 
 
-
 #define BREAK break; }
-     
+#define DONE break
+
 #include "interpret_functions.h"
       
     default:
-- 
GitLab