From 012e50dd87bf27dc7d9a6f42ded0ca91fa68ab16 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Sun, 15 Jun 2008 14:16:05 +0000 Subject: merge revision(s) 16564: * marshal.c (reentrant_check): check reentrance via callcc. [ruby-dev:34802] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_5@17317 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ eval.c | 2 +- marshal.c | 36 ++++++++++++++++++++++++++++++++---- version.h | 2 +- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 61a07d9f05..524cfd72c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ Sun Jun 15 23:12:02 2008 Yukihiro Matsumoto * parse.y (top_local_setup): fixed memory leak bug based on a patch from Roger Pack in [ruby-core:16610]. +Sun Jun 15 23:15:35 2008 Yukihiro Matsumoto + + * marshal.c (reentrant_check): check reentrance via callcc. + [ruby-dev:34802] + Sun Jun 15 23:08:29 2008 NAKAMURA Usaku diff --git a/eval.c b/eval.c index 1c7a0717a4..ab078c6d7a 100644 --- a/eval.c +++ b/eval.c @@ -5469,7 +5469,7 @@ rb_ensure(b_proc, data1, e_proc, data2) } POP_TAG(); retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */ - (*e_proc)(data2); + (*e_proc)(data2); if (prot_tag) return_value(retval); if (state) JUMP_TAG(state); return result; diff --git a/marshal.c b/marshal.c index 39f9cc7478..f8cbaa510d 100644 --- a/marshal.c +++ b/marshal.c @@ -84,6 +84,16 @@ static ID s_dump, s_load, s_mdump, s_mload; static ID s_dump_data, s_load_data, s_alloc; static ID s_getc, s_read, s_write, s_binmode; +static void +reentrant_check(obj, sym) + VALUE obj; + ID sym; +{ + if (RBASIC(obj)->klass) { + rb_raise(rb_eRuntimeError, "%s reentered", rb_id2name(sym)); + } +} + struct dump_arg { VALUE obj; VALUE str, dest; @@ -505,6 +515,7 @@ w_object(obj, arg, limit) volatile VALUE v; v = rb_funcall(obj, s_mdump, 0, 0); + reentrant_check(arg->str, s_mdump); w_class(TYPE_USRMARSHAL, obj, arg, Qfalse); w_object(v, arg, limit); if (ivtbl) w_ivar(0, &c_arg); @@ -514,6 +525,7 @@ w_object(obj, arg, limit) VALUE v; v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); + reentrant_check(arg->str, s_dump); if (TYPE(v) != T_STRING) { rb_raise(rb_eTypeError, "_dump() must return string"); } @@ -658,6 +670,7 @@ w_object(obj, arg, limit) rb_obj_classname(obj)); } v = rb_funcall(obj, s_dump_data, 0); + reentrant_check(arg->str, s_dump_data); w_class(TYPE_DATA, obj, arg, Qtrue); w_object(v, arg, limit); } @@ -690,11 +703,13 @@ static VALUE dump_ensure(arg) struct dump_arg *arg; { + if (RBASIC(arg->str)->klass) return; /* ignore reentrant */ st_free_table(arg->symbols); st_free_table(arg->data); if (arg->taint) { OBJ_TAINT(arg->str); } + return 0; } @@ -747,20 +762,21 @@ marshal_dump(argc, argv) else port = a1; } arg.dest = 0; + arg.str = rb_str_buf_new(0); + RBASIC(arg.str)->klass = 0; if (!NIL_P(port)) { if (!rb_respond_to(port, s_write)) { type_error: rb_raise(rb_eTypeError, "instance of IO needed"); } - arg.str = rb_str_buf_new(0); arg.dest = port; if (rb_respond_to(port, s_binmode)) { rb_funcall2(port, s_binmode, 0, 0); + reentrant_check(arg.str, s_dump_data); } } else { - port = rb_str_buf_new(0); - arg.str = port; + port = arg.str; } arg.symbols = st_init_numtable(); @@ -774,6 +790,7 @@ marshal_dump(argc, argv) w_byte(MARSHAL_MINOR, &arg); rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg); + RBASIC(arg.str)->klass = rb_cString; return port; } @@ -806,6 +823,7 @@ r_byte(arg) else { VALUE src = arg->src; VALUE v = rb_funcall2(src, s_getc, 0, 0); + reentrant_check(arg->data, s_getc); if (NIL_P(v)) rb_eof_error(); c = (unsigned char)FIX2INT(v); } @@ -886,6 +904,7 @@ r_bytes0(len, arg) VALUE src = arg->src; VALUE n = LONG2NUM(len); str = rb_funcall2(src, s_read, 1, &n); + reentrant_check(arg->data, s_read); if (NIL_P(str)) goto too_short; StringValue(str); if (RSTRING(str)->len != len) goto too_short; @@ -1239,6 +1258,7 @@ r_object0(arg, proc, ivp, extmod) *ivp = Qfalse; } v = rb_funcall(klass, s_load, 1, data); + reentrant_check(arg->data, s_load); r_entry(v, arg); } break; @@ -1262,6 +1282,7 @@ r_object0(arg, proc, ivp, extmod) r_entry(v, arg); data = r_object(arg); rb_funcall(v, s_mload, 1, data); + reentrant_check(arg->data, s_mload); } break; @@ -1288,6 +1309,7 @@ r_object0(arg, proc, ivp, extmod) warn = Qfalse; } v = rb_funcall(klass, s_alloc, 0); + reentrant_check(arg->data, s_alloc); } else { v = rb_obj_alloc(klass); @@ -1302,6 +1324,7 @@ r_object0(arg, proc, ivp, extmod) rb_class2name(klass)); } rb_funcall(v, s_load_data, 1, r_object0(arg, 0, 0, extmod)); + reentrant_check(arg->data, s_load_data); } break; @@ -1344,7 +1367,9 @@ r_object0(arg, proc, ivp, extmod) break; } if (proc) { - rb_funcall(proc, rb_intern("call"), 1, v); + ID s_call = + rb_funcall(proc, s_call, 1, v); + reentrant_check(arg->data, s_call); } return v; } @@ -1367,6 +1392,7 @@ static VALUE load_ensure(arg) struct load_arg *arg; { + if (RBASIC(arg->data)->klass) return; /* ignore reentrant */ st_free_table(arg->symbols); return 0; } @@ -1424,9 +1450,11 @@ marshal_load(argc, argv) arg.symbols = st_init_numtable(); arg.data = rb_hash_new(); + RBASIC(arg.data)->klass = 0; if (NIL_P(proc)) arg.proc = 0; else arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); + RBASIC(arg.data)->klass = rb_cHash; return v; } diff --git a/version.h b/version.h index 07850c2490..d1cf0c66e6 100644 --- a/version.h +++ b/version.h @@ -2,7 +2,7 @@ #define RUBY_RELEASE_DATE "2008-06-15" #define RUBY_VERSION_CODE 185 #define RUBY_RELEASE_CODE 20080615 -#define RUBY_PATCHLEVEL 212 +#define RUBY_PATCHLEVEL 213 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 8 -- cgit v1.2.3