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