Fix segfault when running code like "p eval('0'+'+0.1'*5133)" (causing a stack overflow) This at least makes ruby thow a SystemStackError instead of segfaulting. http://redmine.ruby-lang.org/issues/show/1329 Upstream: yes (applied in 1.8.8) Backported for 1.8.6 by a3li@gentoo.org. Index: ruby-1.8.6-p388/eval.c =================================================================== --- ruby-1.8.6-p388.orig/eval.c +++ ruby-1.8.6-p388/eval.c @@ -236,6 +236,7 @@ static VALUE rb_f_binding _((VALUE)); static void rb_f_END _((void)); static VALUE rb_f_block_given_p _((void)); static VALUE block_pass _((VALUE,NODE*)); +static void eval_check_tick _((void)); VALUE rb_cMethod; static VALUE method_call _((int, VALUE*, VALUE)); @@ -2963,6 +2964,7 @@ rb_eval(self, n) goto finish; \ } while (0) + eval_check_tick(); again: if (!node) RETURN(Qnil); @@ -5576,6 +5578,17 @@ stack_check() } } +static void +eval_check_tick() +{ + static int tick; + if ((++tick & 0xff) == 0) { + CHECK_INTS; /* better than nothing */ + stack_check(); + rb_gc_finalize_deferred(); + } +} + static int last_call_status; #define CSTAT_PRIV 1 @@ -5807,7 +5820,6 @@ rb_call0(klass, recv, id, oid, argc, arg NODE *b2; /* OK */ volatile VALUE result = Qnil; int itr; - static int tick; TMP_PROTECT; volatile int safe = -1; @@ -5826,11 +5838,7 @@ rb_call0(klass, recv, id, oid, argc, arg break; } - if ((++tick & 0xff) == 0) { - CHECK_INTS; /* better than nothing */ - stack_check(); - rb_gc_finalize_deferred(); - } + eval_check_tick(); if (argc < 0) { VALUE tmp; VALUE *nargv; @@ -6559,15 +6567,23 @@ eval(self, src, scope, file, line) if (state == TAG_RAISE) { if (strcmp(file, "(eval)") == 0) { VALUE mesg, errat, bt2; + ID id_mesg; + id_mesg = rb_intern("mesg"); errat = get_backtrace(ruby_errinfo); - mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg")); + mesg = rb_attr_get(ruby_errinfo, id_mesg); if (!NIL_P(errat) && TYPE(errat) == T_ARRAY && (bt2 = backtrace(-2), RARRAY(bt2)->len > 0)) { if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) { - rb_str_update(mesg, 0, 0, rb_str_new2(": ")); - rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]); - } + if (OBJ_FROZEN(mesg)) { + VALUE m = rb_str_cat(rb_str_dup(RARRAY(errat)->ptr[0]), ": ", 2); + rb_ivar_set(ruby_errinfo, id_mesg, rb_str_append(m, mesg)); + } + else { + rb_str_update(mesg, 0, 0, rb_str_new2(": ")); + rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]); + } + } RARRAY(errat)->ptr[0] = RARRAY(bt2)->ptr[0]; } }