NTT$B%l%>%J%s%H$N5mEg$H?=$7$^$9!#(B
x86_64$B4D6-$G(BMarshal.dump/load$B$,$&$^$/F/$+$J$$8=>]$KAx6x$7$^$7$?$N$G!"Js(B
$B9p$5$;$F$$$?$@$-$^$9!#(B
$B:F8=%3!<%I$r0J2<$K<($7$^$9!#K\MhEy$7$$$O$:$N(Bobj$B$H(Bobj1$B$,Ey$7$/$J$$$HH=Dj(B
$B$5$l$F$7$^$$$^$9!#(B
---------
obj = Array.new(10000) do
Time.now.to_i + (rand * 10).to_i
end
obj1 = Marshal.load(Marshal.dump(obj))
p obj1 == obj
# ==> false!
---------
$B8D!9$NMWAG$rHf3S$7$F$_$k$H!";d$N4D6-$G$O(Bobj1[6449]$B0J9_$NCM$,68$C$F$7$^$C(B
$B$F$$$^$9!#(BArray$B$ND9$5$,C;$$$H$-$K$OH/@8$7$J$$$H$3$m$r8+$k$H!"$I$&$d$i(BGC
$B$,0-$5$r$7$F$$$k$h$&$G$9!#(B
$BAG?M9M$($G$9$,!"(Bmarshal.c$B$N(Bw_object()$B$N(BFIXNUM$B$N(Bdump$B=hM}$G!"0l;~E*$K@8@.(B
$B$5$l$?(BBignum$B%*%V%8%'%/%H$,(BMarshal.dump$BCf$K2rJ|$5$l$F$7$^$&$N$,LdBj$N$h$&(B
$B$J5$$,$7$^$9!#(B
--------
else if (FIXNUM_P(obj)) {
#if SIZEOF_LONG <= 4
w_byte(TYPE_FIXNUM, arg);
w_long(FIX2INT(obj), arg);
#else
if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) {
w_byte(TYPE_FIXNUM, arg);
w_long(FIX2LONG(obj), arg);
}
else {
w_object(rb_int2big(FIX2LONG(obj)), arg, limit);
^^^^^^^^^^^^^^^^^^^^^^^^^
}
#endif
--------
$B3NG'$7$?4D6-$O0J2<$NDL$j$G$9!#(B
- Red Hat Enterprise Linux Server release 5.2 (Tikanga)
Linux host 2.6.18-92.1.6.el5 #1 SMP Fri Jun 20 02:36:06 EDT 2008
x86_64 x86_64 x86_64 GNU/Linux
- ruby 1.8.6 (2008-08-11 patchlevel 287) [x86_64-linux]
$B0J>e!"$h$m$7$/$*4j$$$7$^$9!#(B
on 01.09.2008 15:02
on 01.09.2008 17:47
$BA0ED$G$9!#(B 2008/09/01 21:56 Kouichi Ushijima <ushijima@nttr.co.jp>: > # ==> false! > --------- Solaris/x86_64$B$G$b:F8=$7$^$7$?!#(B $B0J2<$N%3!<%I$G$b:F8=$9$k$h$&$G$9!#(B obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656] GC.stress = true s = Marshal.dump(obj) obj1 = Marshal.load(s) p obj1 == obj $B$I$&$d$i(Bmarshal.c$B$N(Bw_object()$B$N0J2<$N(Bif$BJ8$N>r7o$,??$K$J$C$F$$$k$h$&$J$N$G$9$,!"(B if (st_lookup(arg->data, obj, &num)) { w_byte(TYPE_LINK, arg); w_long((long)num, arg); return; } dump$BCf$K(BGC$B$,H/@8$9$k$H!"0l;~E*$K@8@.$7$?(BBignum$B%*%V%8%'%/%H$N%"%I%l%9$,(B $B$?$^$?$^F1$8$K$J$C$F$7$^$&$?$a!"(Barg->data$B$N8!:w;~$K8m$C$F0JA0$N%*%V%8%'%/%H(B $B$K%R%C%H$7$F%j%s%/$H$7$F=hM}$5$l$F$7$^$&$h$&$G$9!#(B $BB>$K$b(Bdump$BCf$K0l;~E*$K%*%V%8%'%/%H$r@8@.$7$F$$$kItJ,$,$b$7$"$l$P!"F1$8$h$&(B $B$JLdBj$,H/@8$7$=$&$G$9$M!#(B $BBP1~$H$7$F$O(Barg->data$B$r(BHash$B$K$9$k$H$+$G$7$g$&$+!#(B
on 01.09.2008 17:59
$B$^$D$b$H(B $B$f$-$R$m$G$9(B
In message "Re: [ruby-dev:36086] Re:
x86_64$B4D6-$G(BMarshal.dump$B$NIT6q9g(B"
on Tue, 2 Sep 2008 00:41:51 +0900, "Shugo Maeda"
<shugo@ruby-lang.org> writes:
|$B$I$&$d$i(Bmarshal.c$B$N(Bw_object()$B$N0J2<$N(Bif$BJ8$N>r7o$,??$K$J$C$F$$$k$h$&$J$N$G$9$,!"(B
|
| if (st_lookup(arg->data, obj, &num)) {
| w_byte(TYPE_LINK, arg);
| w_long((long)num, arg);
| return;
| }
|
|dump$BCf$K(BGC$B$,H/@8$9$k$H!"0l;~E*$K@8@.$7$?(BBignum$B%*%V%8%'%/%H$N%"%I%l%9$,(B
|$B$?$^$?$^F1$8$K$J$C$F$7$^$&$?$a!"(Barg->data$B$N8!:w;~$K8m$C$F0JA0$N%*%V%8%'%/%H(B
|$B$K%R%C%H$7$F%j%s%/$H$7$F=hM}$5$l$F$7$^$&$h$&$G$9!#(B
|$BB>$K$b(Bdump$BCf$K0l;~E*$K%*%V%8%'%/%H$r@8@.$7$F$$$kItJ,$,$b$7$"$l$P!"F1$8$h$&(B
|$B$JLdBj$,H/@8$7$=$&$G$9$M!#(B
$B$J$k$[$I!#(B
|$BBP1~$H$7$F$O(Barg->data$B$r(BHash$B$K$9$k$H$+$G$7$g$&$+!#(B
$B$G$O!"$=$N@~$G9T$-$^$7$g$&$+!#Ht9T5!$NCf$G%Q%C%A:n$k2K$,$"$k(B
$B$+$J(B($B$J$5$=$&(B)$B!#(B
on 02.09.2008 07:12
$B$J$+$@$G$9!#(B At Tue, 2 Sep 2008 00:41:51 +0900, Shugo Maeda wrote in [ruby-dev:36086]: > dump$BCf$K(BGC$B$,H/@8$9$k$H!"0l;~E*$K@8@.$7$?(BBignum$B%*%V%8%'%/%H$N%"%I%l%9$,(B > $B$?$^$?$^F1$8$K$J$C$F$7$^$&$?$a!"(Barg->data$B$N8!:w;~$K8m$C$F0JA0$N%*%V%8%'%/%H(B > $B$K%R%C%H$7$F%j%s%/$H$7$F=hM}$5$l$F$7$^$&$h$&$G$9!#(B > $BB>$K$b(Bdump$BCf$K0l;~E*$K%*%V%8%'%/%H$r@8@.$7$F$$$kItJ,$,$b$7$"$l$P!"F1$8$h$&(B > $B$JLdBj$,H/@8$7$=$&$G$9$M!#(B > > $BBP1~$H$7$F$O(Barg->data$B$r(BHash$B$K$9$k$H$+$G$7$g$&$+!#(B $B$=$l$G$O2r7h$7$^$;$s$G$7$?!#(B hash$B$d(Beql?$B$N:FDj5A$N1F6A$rHr$1$k$?$a$K$O!"(Barg->data$B$N%-!<$r(B VALUE$B$NCM<+BN(B(INT2FIX(obj)$B$J$I(B)$B$K$7$J$/$F$O$J$j$^$;$s$,!"$=$&$9(B $B$k$H%^!<%/$NBP>]$G$O$J$/$J$C$F$7$^$$$^$9!#(B $B6qBNE*$K$O!"(Btest/ruby/marshaltest.rb:test_range_cyclic$B$HN>N)$5$;(B $B$k$3$H$OIT2DG=$G$9!#(B $B$b$7$+$7$?$i!"(B[ruby-dev:34312]$B$b$3$l$,860x$+$bCN$l$^$;$s$M$'!#(B # marshal.c$B$G$O(B r16761 $B$b%P%C%/%]!<%H$7$?$[$&$,$$$$$H;W$$$^$9!#(B * 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] Index: intern.h =================================================================== --- intern.h (revision 19063) +++ intern.h (working copy) @@ -258,4 +258,5 @@ 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)); Index: gc.c =================================================================== --- gc.c (revision 19063) +++ gc.c (working copy) @@ -735,4 +735,29 @@ 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; Index: marshal.c =================================================================== --- marshal.c (revision 19063) +++ marshal.c (working copy) @@ -85,14 +85,4 @@ static ID s_dump_data, s_load_data, s_al 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; @@ -101,4 +91,5 @@ struct dump_arg { st_table *data; int taint; + VALUE wrapper; }; @@ -109,4 +100,25 @@ struct dump_call_arg { }; +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) @@ -516,5 +528,5 @@ w_object(obj, arg, limit) 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); @@ -526,5 +538,5 @@ w_object(obj, arg, limit) 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"); @@ -671,5 +683,5 @@ w_object(obj, arg, limit) } 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); @@ -704,7 +716,9 @@ 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); @@ -773,5 +787,5 @@ marshal_dump(argc, argv) 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); } } @@ -783,4 +797,5 @@ marshal_dump(argc, argv) 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; @@ -800,9 +815,31 @@ struct load_arg { 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)); @@ -824,5 +861,5 @@ r_byte(arg) 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); @@ -905,5 +942,5 @@ r_bytes0(len, arg) 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); @@ -968,5 +1005,5 @@ r_entry(v, arg) 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; @@ -1024,12 +1061,13 @@ r_object0(arg, proc, ivp, extmod) 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; @@ -1256,5 +1294,5 @@ r_object0(arg, proc, ivp, extmod) } v = rb_funcall(klass, s_load, 1, data); - reentrant_check(arg->data, s_load); + check_load_arg(arg, s_load); r_entry(v, arg); } @@ -1280,5 +1318,5 @@ r_object0(arg, proc, ivp, extmod) data = r_object(arg); rb_funcall(v, s_mload, 1, data); - reentrant_check(arg->data, s_mload); + check_load_arg(arg, s_mload); } break; @@ -1307,5 +1345,5 @@ r_object0(arg, proc, ivp, extmod) } v = rb_funcall(klass, s_alloc, 0); - reentrant_check(arg->data, s_alloc); + check_load_arg(arg, s_alloc); } else { @@ -1322,5 +1360,5 @@ r_object0(arg, proc, ivp, extmod) } 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; @@ -1366,5 +1404,5 @@ 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; @@ -1389,6 +1427,9 @@ 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; } @@ -1432,5 +1473,8 @@ 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); @@ -1447,9 +1491,5 @@ 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; + if (!NIL_P(proc)) arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); RBASIC(arg.data)->klass = rb_cHash; Index: test/ruby/test_marshal.rb =================================================================== --- test/ruby/test_marshal.rb (revision 19063) +++ test/ruby/test_marshal.rb (working copy) @@ -13,9 +13,15 @@ class TestMarshal < Test::Unit::TestCase 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 Index: test/ruby/marshaltestlib.rb =================================================================== --- test/ruby/marshaltestlib.rb (revision 19063) +++ test/ruby/marshaltestlib.rb (working copy) @@ -194,4 +194,10 @@ module MarshalTestLib end + def test_fixnum_64bit + obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656] + + marshal_equal(obj) + end + def test_float marshal_equal(-1.0)
on 02.09.2008 09:18
$BA0ED$G$9!#(B 2008/09/02 14:06 Nobuyoshi Nakada <nobu@ruby-lang.org>: > $B$=$l$G$O2r7h$7$^$;$s$G$7$?!#(B > > hash$B$d(Beql?$B$N:FDj5A$N1F6A$rHr$1$k$?$a$K$O!"(Barg->data$B$N%-!<$r(B > VALUE$B$NCM<+BN(B(INT2FIX(obj)$B$J$I(B)$B$K$7$J$/$F$O$J$j$^$;$s$,!"$=$&$9(B > $B$k$H%^!<%/$NBP>]$G$O$J$/$J$C$F$7$^$$$^$9!#(B $B%-!<$G$O$J$/$FCM$NJ}$r(Brb_assoc_new($BHV9f(B, $B%*%V%8%'%/%H(B)$B$N$h$&$J7A$K$9$k(B $B$3$H$r9M$($F$^$7$?!#$A$g$C$HL5BL$G$9$,!#(B > * 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] $B$A$g$&$I:#D+$N0\F0Cf$K(Btrunk$B$G$O(BT_DATA$B$G(Bwrap$B$7$F%^!<%/$7$F$k$3$H$K5$IU$$$?$N(B $B$G$9$,!"$3$NJ}?K$,$h$5$=$&$G$9$M!#(B $B$"$H!"3:Ev2U=j$G:n$C$F$$$k(BBignum$B%*%V%8%'%/%H$OL@$i$+$K8e$G;H$o$l$k$3$H$O$J$$(B $B$N$G!"(Bw_object()$B$K(Barg->data$B$N8!:w!&DI2C$r$d$a$k%*%W%7%g%s$,$"$C$F$b$$$$$+$b(B $B$7$l$J$$$H;W$$$^$7$?!#(B $B:#2s$_$?$$$JFC<l$J%1!<%9(B($BHyL/$J%5%$%:$N(BFixnum$B$r$?$/$5$s(Bdump$B$9$k(B)$B$G$J$$$H(B $B0UL#$,$J$$$+$b$7$l$^$;$s$,!#(B
on 02.09.2008 15:09
$B5mEg$G$9!#(B > * 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] $B$"$j$,$H$&$4$6$$$^$9!#2r7h$5$l$F$$$k$3$H$r3NG'$7$^$7$?!#(B