From d834f1b537d94edd942a8393101f2a06264c1098 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Sun, 15 Jun 2008 14:17:11 +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_6@17319 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- marshal.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'marshal.c') diff --git a/marshal.c b/marshal.c index 256775bf7e..0c991fab98 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; } -- cgit v1.2.3