diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | gc.c | 25 | ||||
-rw-r--r-- | intern.h | 1 | ||||
-rw-r--r-- | marshal.c | 107 | ||||
-rw-r--r-- | test/ruby/marshaltestlib.rb | 6 | ||||
-rw-r--r-- | test/ruby/test_marshal.rb | 6 | ||||
-rw-r--r-- | version.h | 8 |
7 files changed, 129 insertions, 38 deletions
@@ -1,3 +1,17 @@ +Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * marshal.c (marshal_load): arg.data is no longer a VALUE but a + st_table, and freed in load_ensure. pointed out by pegacorn. + [ruby-dev:37008] + +Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * gc.c (rb_mark_set): new function to mark keys. + + * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark + data entries. backport from trunk r13527,r13528,r13961,r16533. + [ruby-dev:36082] + Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org> * win32/win32.c (filetime_to_timeval): new function, split from @@ -724,6 +724,31 @@ rb_mark_tbl(tbl) } static int +mark_key(key, value, lev) + VALUE key, value; + int lev; +{ + gc_mark(key, lev); + return ST_CONTINUE; +} + +static void +mark_set(tbl, lev) + st_table *tbl; + int lev; +{ + if (!tbl) return; + st_foreach(tbl, mark_key, lev); +} + +void +rb_mark_set(tbl) + st_table *tbl; +{ + mark_set(tbl, 0); +} + +static int mark_keyvalue(key, value, lev) VALUE key; VALUE value; @@ -256,6 +256,7 @@ int rb_during_gc _((void)); char *rb_source_filename _((const char*)); void rb_gc_mark_locations _((VALUE*, VALUE*)); void rb_mark_tbl _((struct st_table*)); +void rb_mark_set _((struct st_table*)); void rb_mark_hash _((struct st_table*)); void rb_gc_mark_maybe _((VALUE)); void rb_gc_mark _((VALUE)); @@ -84,22 +84,13 @@ static ID s_dump, s_load, s_mdump, s_mload; static ID s_dump_data, s_load_data, s_alloc, s_call; static ID s_getc, s_read, s_write, s_binmode; -static void -reentrant_check(obj, sym) - VALUE obj; - ID sym; -{ - if (obj && RBASIC(obj)->klass) { - rb_raise(rb_eRuntimeError, "%s reentered", rb_id2name(sym)); - } -} - struct dump_arg { VALUE obj; VALUE str, dest; st_table *symbols; st_table *data; int taint; + VALUE wrapper; }; struct dump_call_arg { @@ -108,6 +99,27 @@ struct dump_call_arg { int limit; }; +static void +check_dump_arg(arg, sym) + struct dump_arg *arg; + ID sym; +{ + if (!DATA_PTR(arg->wrapper)) { + rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s", + rb_id2name(sym)); + } +} + +static void +mark_dump_arg(ptr) + void *ptr; +{ + struct dump_arg *p = ptr; + if (!ptr) + return; + rb_mark_set(p->data); +} + static VALUE class2path(klass) VALUE klass; @@ -515,7 +527,7 @@ w_object(obj, arg, limit) volatile VALUE v; v = rb_funcall(obj, s_mdump, 0, 0); - reentrant_check(arg->str, s_mdump); + check_dump_arg(arg, s_mdump); w_class(TYPE_USRMARSHAL, obj, arg, Qfalse); w_object(v, arg, limit); if (ivtbl) w_ivar(0, &c_arg); @@ -525,7 +537,7 @@ w_object(obj, arg, limit) VALUE v; v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); - reentrant_check(arg->str, s_dump); + check_dump_arg(arg, s_dump); if (TYPE(v) != T_STRING) { rb_raise(rb_eTypeError, "_dump() must return string"); } @@ -670,7 +682,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); + check_dump_arg(arg, s_dump_data); w_class(TYPE_DATA, obj, arg, Qtrue); w_object(v, arg, limit); } @@ -703,9 +715,11 @@ static VALUE dump_ensure(arg) struct dump_arg *arg; { - if (RBASIC(arg->str)->klass) return 0; /* ignore reentrant */ + if (!DATA_PTR(arg->wrapper)) return 0; st_free_table(arg->symbols); st_free_table(arg->data); + DATA_PTR(arg->wrapper) = 0; + arg->wrapper = 0; if (arg->taint) { OBJ_TAINT(arg->str); } @@ -772,7 +786,7 @@ marshal_dump(argc, argv) arg.dest = port; if (rb_respond_to(port, s_binmode)) { rb_funcall2(port, s_binmode, 0, 0); - reentrant_check(arg.str, s_dump_data); + check_dump_arg(&arg, s_dump_data); } } else { @@ -782,6 +796,7 @@ marshal_dump(argc, argv) arg.symbols = st_init_numtable(); arg.data = st_init_numtable(); arg.taint = Qfalse; + arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg); c_arg.obj = obj; c_arg.arg = &arg; c_arg.limit = limit; @@ -799,11 +814,33 @@ struct load_arg { VALUE src; long offset; st_table *symbols; - VALUE data; + st_table *data; VALUE proc; int taint; + VALUE wrapper; }; +static void +check_load_arg(arg, sym) + struct load_arg *arg; + ID sym; +{ + if (!DATA_PTR(arg->wrapper)) { + rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s", + rb_id2name(sym)); + } +} + +static void +mark_load_arg(ptr) + void *ptr; +{ + struct load_arg *p = ptr; + if (!ptr) + return; + rb_mark_tbl(p->data); +} + static VALUE r_object _((struct load_arg *arg)); static int @@ -823,7 +860,7 @@ r_byte(arg) else { VALUE src = arg->src; VALUE v = rb_funcall2(src, s_getc, 0, 0); - reentrant_check(arg->data, s_getc); + check_load_arg(arg, s_getc); if (NIL_P(v)) rb_eof_error(); c = (unsigned char)FIX2INT(v); } @@ -904,7 +941,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); + check_load_arg(arg, s_read); if (NIL_P(str)) goto too_short; StringValue(str); if (RSTRING(str)->len != len) goto too_short; @@ -967,7 +1004,7 @@ r_entry(v, arg) VALUE v; struct load_arg *arg; { - rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v); + st_insert(arg->data, arg->data->num_entries, (st_data_t)v); if (arg->taint) OBJ_TAINT(v); return v; } @@ -1023,14 +1060,15 @@ r_object0(arg, proc, ivp, extmod) VALUE v = Qnil; int type = r_byte(arg); long id; + st_data_t link; switch (type) { case TYPE_LINK: id = r_long(arg); - v = rb_hash_aref(arg->data, LONG2FIX(id)); - if (NIL_P(v)) { + if (!st_lookup(arg->data, (st_data_t)id, &link)) { rb_raise(rb_eArgError, "dump format error (unlinked)"); } + v = (st_data_t)link; return v; case TYPE_IVAR: @@ -1255,7 +1293,7 @@ r_object0(arg, proc, ivp, extmod) *ivp = Qfalse; } v = rb_funcall(klass, s_load, 1, data); - reentrant_check(arg->data, s_load); + check_load_arg(arg, s_load); r_entry(v, arg); } break; @@ -1279,7 +1317,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); + check_load_arg(arg, s_mload); } break; @@ -1306,7 +1344,7 @@ r_object0(arg, proc, ivp, extmod) warn = Qfalse; } v = rb_funcall(klass, s_alloc, 0); - reentrant_check(arg->data, s_alloc); + check_load_arg(arg, s_alloc); } else { v = rb_obj_alloc(klass); @@ -1321,7 +1359,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); + check_load_arg(arg, s_load_data); } break; @@ -1365,7 +1403,7 @@ r_object0(arg, proc, ivp, extmod) } if (proc) { rb_funcall(proc, s_call, 1, v); - reentrant_check(arg->data, s_call); + check_load_arg(arg, s_call); } return v; } @@ -1388,8 +1426,11 @@ static VALUE load_ensure(arg) struct load_arg *arg; { - if (RBASIC(arg->data)->klass) return 0; /* ignore reentrant */ + if (!DATA_PTR(arg->wrapper)) return 0; st_free_table(arg->symbols); + st_free_table(arg->data); + DATA_PTR(arg->wrapper) = 0; + arg->wrapper = 0; return 0; } @@ -1431,7 +1472,10 @@ marshal_load(argc, argv) } arg.src = port; arg.offset = 0; - arg.data = 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); major = r_byte(&arg); minor = r_byte(&arg); @@ -1446,13 +1490,8 @@ marshal_load(argc, argv) MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); } - 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; + if (!NIL_P(proc)) arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); - RBASIC(arg.data)->klass = rb_cHash; return v; } diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb index 891f43b1f7..ae60cd8479 100644 --- a/test/ruby/marshaltestlib.rb +++ b/test/ruby/marshaltestlib.rb @@ -193,6 +193,12 @@ module MarshalTestLib 1.instance_eval { remove_instance_variable("@iv") } end + def test_fixnum_64bit + obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656] + + marshal_equal(obj) + end + def test_float marshal_equal(-1.0) marshal_equal(0.0) diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index 11f3583076..68f50ff728 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -12,11 +12,17 @@ class TestMarshal < Test::Unit::TestCase include MarshalTestLib def encode(o) + stress, GC.stress = GC.stress, true Marshal.dump(o) + ensure + GC.stress = stress end def decode(s) + stress, GC.stress = GC.stress, true Marshal.load(s) + ensure + GC.stress = stress end def fact(n) @@ -1,15 +1,15 @@ #define RUBY_VERSION "1.8.7" -#define RUBY_RELEASE_DATE "2009-01-21" +#define RUBY_RELEASE_DATE "2009-01-22" #define RUBY_VERSION_CODE 187 -#define RUBY_RELEASE_CODE 20090121 -#define RUBY_PATCHLEVEL 91 +#define RUBY_RELEASE_CODE 20090122 +#define RUBY_PATCHLEVEL 92 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 8 #define RUBY_VERSION_TEENY 7 #define RUBY_RELEASE_YEAR 2009 #define RUBY_RELEASE_MONTH 1 -#define RUBY_RELEASE_DAY 21 +#define RUBY_RELEASE_DAY 22 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; |