From 72facac57c1e086b0be8ef86773e0eb7fe14ff1f Mon Sep 17 00:00:00 2001 From: matz Date: Sat, 7 Nov 2009 02:45:08 +0000 Subject: * vm_insnhelper.c (vm_push_frame): add CHECK_STACK_OVERFLOW. [ruby-dev:39592] * eval.c (rb_longjmp): add 1 level backtrace for sysstack_error without calling any method to prevent further stack overflow. * eval.c (make_exception): don't call #exception for sysstack_error to prevent stack overflow. * proc.c (Init_Proc): don't freeze sysstack_error. * eval.c (rb_longjmp): move reentrant check after exception preparation. git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@25680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 16 ++++++++++++++++ eval.c | 31 +++++++++++++++++++------------ proc.c | 1 - vm_insnhelper.c | 4 +++- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 187157498..c4cebd340 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Fri Nov 6 18:33:47 2009 Yukihiro Matsumoto + + * vm_insnhelper.c (vm_push_frame): add CHECK_STACK_OVERFLOW. + [ruby-dev:39592] + + * eval.c (rb_longjmp): add 1 level backtrace for sysstack_error + without calling any method to prevent further stack overflow. + + * eval.c (make_exception): don't call #exception for + sysstack_error to prevent stack overflow. + + * proc.c (Init_Proc): don't freeze sysstack_error. + + * eval.c (rb_longjmp): move reentrant check after exception + preparation. + Fri Nov 6 17:13:45 2009 Nobuyoshi Nakada * lib/mkmf.rb (create_header): split the line by tabs. diff --git a/eval.c b/eval.c index f33d80360..c3bde6b9e 100644 --- a/eval.c +++ b/eval.c @@ -358,12 +358,6 @@ rb_longjmp(int tag, volatile VALUE mesg) const char *file; volatile int line = 0; - if (rb_threadptr_set_raised(th)) { - th->errinfo = exception_error; - rb_threadptr_reset_raised(th); - JUMP_TAG(TAG_FATAL); - } - if (NIL_P(mesg)) mesg = th->errinfo; if (NIL_P(mesg)) { @@ -373,13 +367,19 @@ rb_longjmp(int tag, volatile VALUE mesg) file = rb_sourcefile(); if (file) line = rb_sourceline(); if (file && !NIL_P(mesg)) { - at = get_backtrace(mesg); - if (NIL_P(at)) { - at = rb_make_backtrace(); - if (OBJ_FROZEN(mesg)) { - mesg = rb_obj_dup(mesg); + if (mesg == sysstack_error) { + at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line); + rb_iv_set(mesg, "bt", at); + } + else { + at = get_backtrace(mesg); + if (NIL_P(at)) { + at = rb_make_backtrace(); + if (OBJ_FROZEN(mesg)) { + mesg = rb_obj_dup(mesg); + } + set_backtrace(mesg, at); } - set_backtrace(mesg, at); } } if (!NIL_P(mesg)) { @@ -414,6 +414,12 @@ rb_longjmp(int tag, volatile VALUE mesg) } } + if (rb_threadptr_set_raised(th)) { + th->errinfo = exception_error; + rb_threadptr_reset_raised(th); + JUMP_TAG(TAG_FATAL); + } + rb_trap_restore_mask(); if (tag != TAG_FATAL) { @@ -520,6 +526,7 @@ make_exception(int argc, VALUE *argv, int isstr) case 3: n = 1; exception_call: + if (argv[0] == sysstack_error) return argv[0]; CONST_ID(exception, "exception"); mesg = rb_check_funcall(argv[0], exception, n, argv+1); if (mesg == Qundef) { diff --git a/proc.c b/proc.c index 468ca467b..daf8c673f 100644 --- a/proc.c +++ b/proc.c @@ -2043,7 +2043,6 @@ Init_Proc(void) sysstack_error = rb_exc_new3(rb_eSysStackError, rb_obj_freeze(rb_str_new2("stack level too deep"))); OBJ_TAINT(sysstack_error); - OBJ_FREEZE(sysstack_error); /* utility functions */ rb_define_global_function("proc", rb_block_proc, 0); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 5b965d215..7974a75cd 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -26,9 +26,11 @@ vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq, const VALUE *pc, VALUE *sp, VALUE *lfp, int local_size) { - rb_control_frame_t * const cfp = th->cfp = th->cfp - 1; + rb_control_frame_t * const cfp = th->cfp - 1; int i; + CHECK_STACK_OVERFLOW(th->cfp, local_size); + th->cfp = cfp; /* setup vm value stack */ /* nil initialize */ -- cgit