From c31e7c1e8b2895ef33204938487597e2b3acaaf7 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 2 Mar 2012 02:45:35 +0000 Subject: merge revision(s) 25230,34866: * marshal.c (struct {dump,load}_arg): manage with dfree, instead of using local variable which may be moved by context switch. [ruby-dev:39425] * marshal.c (mark_dump_arg): mark destination string. patch by Vit Ondruch. [Bug #4339] * marshal.c (clear_dump_arg, clear_load_arg): clean up also data tables as same as symbols tables. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@34867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- marshal.c | 145 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 73 insertions(+), 72 deletions(-) (limited to 'marshal.c') diff --git a/marshal.c b/marshal.c index 35e0d60374..632f6cae4f 100644 --- a/marshal.c +++ b/marshal.c @@ -85,12 +85,10 @@ static ID s_dump_data, s_load_data, s_alloc, s_call; static ID s_getc, s_read, s_write, s_binmode; struct dump_arg { - VALUE obj; VALUE str, dest; st_table *symbols; st_table *data; int taint; - VALUE wrapper; }; struct dump_call_arg { @@ -104,20 +102,31 @@ check_dump_arg(arg, sym) struct dump_arg *arg; ID sym; { - if (!DATA_PTR(arg->wrapper)) { + if (!arg->symbols) { rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s", rb_id2name(sym)); } } +static void clear_dump_arg _((struct dump_arg *arg)); + static void mark_dump_arg(ptr) void *ptr; { struct dump_arg *p = ptr; - if (!ptr) + if (!p->symbols) return; rb_mark_set(p->data); + rb_gc_mark(p->str); +} + +static void +free_dump_arg(ptr) + void *ptr; +{ + clear_dump_arg(ptr); + xfree(ptr); } static VALUE @@ -699,32 +708,18 @@ w_object(obj, arg, limit) } } -static VALUE -dump(arg) - struct dump_call_arg *arg; -{ - w_object(arg->obj, arg->arg, arg->limit); - if (arg->arg->dest) { - rb_io_write(arg->arg->dest, arg->arg->str); - rb_str_resize(arg->arg->str, 0); - } - return 0; -} - -static VALUE -dump_ensure(arg) +static void +clear_dump_arg(arg) struct dump_arg *arg; { - if (!DATA_PTR(arg->wrapper)) return 0; + if (!arg->symbols) return; st_free_table(arg->symbols); + arg->symbols = 0; st_free_table(arg->data); - DATA_PTR(arg->wrapper) = 0; - arg->wrapper = 0; + arg->data = 0; if (arg->taint) { OBJ_TAINT(arg->str); } - - return 0; } /* @@ -760,8 +755,8 @@ marshal_dump(argc, argv) { VALUE obj, port, a1, a2; int limit = -1; - struct dump_arg arg; - struct dump_call_arg c_arg; + struct dump_arg *arg; + VALUE wrapper; port = Qnil; rb_scan_args(argc, argv, "12", &obj, &a1, &a2); @@ -775,37 +770,40 @@ marshal_dump(argc, argv) else if (NIL_P(a1)) goto type_error; else port = a1; } - arg.dest = 0; - arg.symbols = st_init_numtable(); - arg.data = st_init_numtable(); - arg.taint = Qfalse; - arg.str = rb_str_buf_new(0); - RBASIC(arg.str)->klass = 0; - arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg); + wrapper = Data_Make_Struct(rb_cData, struct dump_arg, mark_dump_arg, free_dump_arg, arg); + arg->dest = 0; + arg->symbols = st_init_numtable(); + arg->data = st_init_numtable(); + arg->taint = Qfalse; + 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.dest = port; + arg->dest = port; if (rb_respond_to(port, s_binmode)) { rb_funcall2(port, s_binmode, 0, 0); - check_dump_arg(&arg, s_binmode); + check_dump_arg(arg, s_binmode); } } else { - port = arg.str; + port = arg->str; } - c_arg.obj = obj; - c_arg.arg = &arg; - c_arg.limit = limit; + w_byte(MARSHAL_MAJOR, arg); + w_byte(MARSHAL_MINOR, arg); - w_byte(MARSHAL_MAJOR, &arg); - w_byte(MARSHAL_MINOR, &arg); + w_object(obj, arg, limit); + if (arg->dest) { + rb_io_write(arg->dest, arg->str); + rb_str_resize(arg->str, 0); + } - rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg); - RBASIC(arg.str)->klass = rb_cString; + RBASIC(arg->str)->klass = rb_cString; + clear_dump_arg(arg); + RB_GC_GUARD(wrapper); return port; } @@ -817,7 +815,6 @@ struct load_arg { st_table *data; VALUE proc; int taint; - VALUE wrapper; }; static void @@ -825,22 +822,31 @@ check_load_arg(arg, sym) struct load_arg *arg; ID sym; { - if (!DATA_PTR(arg->wrapper)) { + if (!arg->symbols) { rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s", rb_id2name(sym)); } } +static void clear_load_arg _((struct load_arg *arg)); + static void mark_load_arg(ptr) void *ptr; { struct load_arg *p = ptr; - if (!ptr) + if (!p->symbols) return; rb_mark_tbl(p->data); } +static void +free_load_arg(void *ptr) +{ + clear_load_arg(ptr); + xfree(ptr); +} + static VALUE r_object _((struct load_arg *arg)); static int @@ -1415,23 +1421,15 @@ r_object(arg) return r_object0(arg, arg->proc, 0, Qnil); } -static VALUE -load(arg) - struct load_arg *arg; -{ - return r_object(arg); -} - -static VALUE -load_ensure(arg) +static void +clear_load_arg(arg) struct load_arg *arg; { - if (!DATA_PTR(arg->wrapper)) return 0; + if (!arg->symbols) return; st_free_table(arg->symbols); + arg->symbols = 0; st_free_table(arg->data); - DATA_PTR(arg->wrapper) = 0; - arg->wrapper = 0; - return 0; + arg->data = 0; } /* @@ -1452,8 +1450,8 @@ marshal_load(argc, argv) { VALUE port, proc; int major, minor, taint = Qfalse; - VALUE v; - struct load_arg arg; + VALUE v, wrapper; + struct load_arg *arg; rb_scan_args(argc, argv, "11", &port, &proc); v = rb_check_string_type(port); @@ -1470,17 +1468,18 @@ marshal_load(argc, argv) else { rb_raise(rb_eTypeError, "instance of IO needed"); } - arg.src = port; - arg.offset = 0; - arg.symbols = st_init_numtable(); - arg.data = st_init_numtable(); - arg.proc = 0; - arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg); - arg.taint = taint; - - major = r_byte(&arg); - minor = r_byte(&arg); + wrapper = Data_Make_Struct(rb_cData, struct load_arg, mark_load_arg, free_load_arg, arg); + arg->src = port; + arg->offset = 0; + arg->symbols = st_init_numtable(); + arg->data = st_init_numtable(); + arg->proc = 0; + arg->taint = taint; + + major = r_byte(arg); + minor = r_byte(arg); if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) { + clear_load_arg(arg); rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\ \tformat version %d.%d required; %d.%d given", MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); @@ -1491,8 +1490,10 @@ marshal_load(argc, argv) MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); } - if (!NIL_P(proc)) arg.proc = proc; - v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); + if (!NIL_P(proc)) arg->proc = proc; + v = r_object(arg); + clear_load_arg(arg); + RB_GC_GUARD(wrapper); return v; } -- cgit v1.2.3