[Bug #3463] 1.9.2-preview3 $B$G(B [BUG] gc_sweep(): unknown data type 0x0

e$B%A%1%C%He(B #3463 e$B$,99?7$5$l$^$7$?!#e(B (by Tomoyuki C.)

e$B%U%!%$%ke(B marshal.patch e$BDI2Ce(B

e$B$9$_$^$;$s!“@hDxE:IU$7$?%Q%C%A$OLdBj$,$”$j$^$7$?!#e(B
struct dump_arg::str
e$B$,;X$9%9%m%C%H$,0lC62s<}$5$l$FB>$N%%V%8%'%/%H$K3d$jEv$F$i$l$F$$$?;~$K4V0c$C$Fe(B
taint e$B$7$F$7$^$$$=$&$G$9!#e(B
T_DATA e$B7?$N%
%V%8%'%/%H$KEPO?$9$ke(B free e$B4X?t$NCf$G$O9=B$BN$,e(B
VALUE
e$B7?$G;}$C$F$$$ke(BRubye$B$N;2>H$O0l@Z$5$o$C$F$O$$$1$J$$$G$9$M!#e(B

struct dump_arg e$B$Ne(B str e$B$Oe(B w_nbytes e$B$G=q$-9~$`;~$Ke(B
OBJ_TAINT/OBJ_UNTRUST
e$B$9$l$PNI$$$N$G$O$J$$$+$H9M$(%Q%C%A$r=q$-D>$7$^$7$?!#e(B
make test-all
e$B$G%(%i!<$,A}$($J$$$3$H$H!"0l1~0J2<$N$h$&$J4JC1$J3NG’$r$7$^$7$?!#e(B

obj = Object.new
=> #Object:0x8d3680c
Marshal.dump(obj).tainted?
=> false
obj.taint
=> #Object:0x8d3680c
Marshal.dump(obj).tainted?
=> true


http://redmine.ruby-lang.org/issues/show/3463

e$B$J$+$@$G$9!#e(B

At Tue, 22 Jun 2010 19:49:59 +0900,
Tomoyuki C. wrote in [ruby-dev:41672]:

e$B$9$_$^$;$s!"@hDxE:IU$7$?%Q%C%A$OLdBj$,$"$j$^$7$?!#e(B
struct dump_arg::str e$B$,;X$9%9%m%C%H$,0lC62s<}$5$l$FB>$N%%V%8%'e(B
e$B%/%H$K3d$jEv$F$i$l$F$$$?;~$K4V0c$C$Fe(B taint e$B$7$F$7$^$$$=$&$G$9!#e(B
T_DATA e$B7?$N%
%V%8%’%/%H$KEPO?$9$ke(B free e$B4X?t$NCf$G$O9=B$BN$,e(B
VALUE e$B7?$G;}$C$F$$$ke(BRubye$B$N;2>H$O0l@Z$5$o$C$F$O$$$1$J$$$G$9$M!#e(B

finaliser_at_exite$B$N;~E@$G$O!"?7$7$$%*%V%8%’%/%H$,3d$jEv$F$i$l$ke(B
e$B$3$H$O9M$($J$/$F$b$$$$$s$8$c$J$$$+$H;W$$$^$9$,!#e(B

struct dump_arg e$B$Ne(B str e$B$Oe(B w_nbytes e$B$G=q$-9~$`;~$Ke(B
OBJ_TAINT/OBJ_UNTRUST e$B$9$l$PNI$$$N$G$O$J$$$+$H9M$(%Q%C%A$r=q$-e(B
e$BD>$7$^$7$?!#e(B
make test-all e$B$G%(%i!<$,A}$($J$$$3$H$H!"0l1~0J2<$N$h$&$J4JC1$Je(B
e$B3NG’$r$7$^$7$?!#e(B

e$B$h$5$=$&$K8+$($^$9!#F~$l$A$c$C$F$$$$$s$8$c$J$$$G$9$+$M!#e(B

e$B6a1J$H?=$7$^$9!#e(B

e$B%Q%C%A$N%l%S%e!<$"$j$,$H$&$4$6$$$^$9!#e(B

(2010/06/22 21:02), Nobuyoshi N. wrote:
(snip)

finaliser_at_exite$B$N;~E@$G$O!"?7$7$$%*%V%8%’%/%H$,3d$jEv$F$i$l$ke(B
e$B$3$H$O9M$($J$/$F$b$$$$$s$8$c$J$$$+$H;W$$$^$9$,!#e(B
clear_dump_arg e$B$Ke(B arg->str e$B$Ne(B flags e$B$,e(B 0
e$B$GMh$F$?;~$O!"2<$N$h$&$Je(B
e$B%3!<%k%9%?%C%/$G$7$?!#IaDL$K%a%=%C%I8F$S=P$7$N4V$KCY1d$5$l$?e(B
free e$B4X?t$N8F$S=P$7$,64$_9~$^$l$F$$$k$h$&$G$9!#e(B

e$B$H$3$m$G!"C1$K6=L#$+$i?V$$$F$$?$$$N$G$9$,!"$J$<$3$N$h$&$Ke(B
T_DATAe$B7?%*%V%8%’%/%H$N2rJ|$OCY1d$5$l$F$k$s$G$7$g$&!#e(B
GC e$B$G$NDd;
;~4V$rJ,;6$5$;$k$?$a$G$7$g$&$+!)e(B

#0 clear_dump_arg (arg=0xa9f63c0) at marshal.c:856
#1 0x0807cec2 in free_dump_arg (ptr=0xa9f63c0) at marshal.c:175
#2 0x080641ad in run_final (objspace=0x9829808, obj=167215020) at
gc.c:2601
#3 0x08062a17 in finalize_list (objspace=0x9829808, p=0x9f77fac) at
gc.c:1806
#4 0x0806422a in finalize_deferred (objspace=0x9829808) at gc.c:2617
#5 0x0806423d in gc_finalize_deferred (objspace=0x9829808) at gc.c:2624
#6 0x08064263 in rb_gc_finalize_deferred () at gc.c:2631
#7 0x0814922c in rb_threadptr_execute_interrupts_rec (th=0xb5023148,
sched_depth=0) at thread.c:1295
#8 0x08149312 in rb_threadptr_execute_interrupts (th=0xb5023148)
at thread.c:1323
#9 0x081354e3 in vm_call_method (th=0xb5023148, cfp=0xb6bfe980, num=0,
blockptr=0x0, flag=0, id=784, me=0x9869b60, recv=7538958)
at vm_insnhelper.c:669
#10 0x081394c3 in vm_exec_core (th=0xb5023148, initial=0) at
insns.def:999
#11 0x0814418d in vm_exec (th=0xb5023148) at vm.c:1139

Chikanaga Tomoyuki
Nippon Control System Corp.

e$B$J$+$@$G$9!#e(B

At Wed, 23 Jun 2010 09:27:11 +0900,
Tomoyuki C. wrote in [ruby-dev:41677]:

finaliser_at_exite$B$N;~E@$G$O!"?7$7$$%*%V%8%’%/%H$,3d$jEv$F$i$l$ke(B
e$B$3$H$O9M$($J$/$F$b$$$$$s$8$c$J$$$+$H;W$$$^$9$,!#e(B
clear_dump_arg e$B$Ke(B arg->str e$B$Ne(B flags e$B$,e(B 0 e$B$GMh$F$?;~$O!"2<$N$h$&$Je(B
e$B%3!<%k%9%?%C%/$G$7$?!#IaDL$K%a%=%C%I8F$S=P$7$N4V$KCY1d$5$l$?e(B
free e$B4X?t$N8F$S=P$7$,64$_9~$^$l$F$$$k$h$&$G$9!#e(B

e$B$&$C$+$j$7$F$^$7$?!#e(B

e$B$H$3$m$G!"C1$K6=L#$+$i?V$$$F$$?$$$N$G$9$,!"$J$<$3$N$h$&$Ke(B
T_DATAe$B7?%*%V%8%’%/%H$N2rJ|$OCY1d$5$l$F$k$s$G$7$g$&!#e(B
GC e$B$G$NDd;
;~4V$rJ,;6$5$;$k$?$a$G$7$g$&$+!)e(B

dfreee$B4X?t$N8F$S=P$7Cf$K%*%V%8%’%/%H$N3d$jEv$F$r$9$k3HD%%i%$%V%ie(B
e$B%j$,$"$C$?$N$G!"e(Bmark phasee$B$HJ,N%$7$?$s$G$7$?!#e(B

e$B$D$$$G$K!"e(BTAINTEDe$B$He(BUNTRUSTEDe$B$r$R$H$^$H$a$K07$&$h$&$K$7$F$_$^$7$?!#e(B
e$B$3$l$G$I$&$G$7$g$&!#e(B

diff --git a/marshal.c b/marshal.c
index fa91afa…3263a57 100644
— a/marshal.c
+++ b/marshal.c
@@ -131,14 +131,16 @@ rb_marshal_define_compat(VALUE newclass, VALUE
oldclass, VALUE (*dumper)(VALUE),
st_insert(compat_allocator_tbl, (st_data_t)allocator,
(st_data_t)compat);
}

+#define MARSHAL_INFECTION (FL_TAINT|FL_UNTRUSTED)
+typedef char ruby_check_marshal_viral_flags[MARSHAL_INFECTION ==
(int)MARSHAL_INFECTION ? 1 : -1];
+
struct dump_arg {
VALUE str, dest;
st_table *symbols;
st_table *data;

  • int taint;
  • int untrust;
    st_table *compat_tbl;
    st_table *encodings;
  • int infection;
    };

struct dump_call_arg {
@@ -224,9 +226,8 @@ w_nbyte(const char *s, long n, struct dump_arg *arg)
{
VALUE buf = arg->str;
rb_str_buf_cat(buf, s, n);

  • RBASIC(buf)->flags |= arg->infection;
    if (arg->dest && RSTRING_LEN(buf) >= BUFSIZ) {
  • if (arg->taint) OBJ_TAINT(buf);
  • if (arg->untrust) OBJ_UNTRUST(buf);
    rb_io_write(arg->dest, buf);
    rb_str_resize(buf, 0);
    }
    @@ -636,8 +637,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
    w_symbol(SYM2ID(obj), arg);
    }
    else {
  • if (OBJ_TAINTED(obj)) arg->taint = TRUE;
  • if (OBJ_UNTRUSTED(obj)) arg->untrust = TRUE;
  • arg->infection |= FL_TEST(obj, MARSHAL_INFECTION);

    if (rb_respond_to(obj, s_mdump)) {
    volatile VALUE v;
    @@ -856,12 +856,6 @@ clear_dump_arg(struct dump_arg *arg)
    st_free_table(arg->encodings);
    arg->encodings = 0;
    }

  • if (arg->taint) {
  • OBJ_TAINT(arg->str);
  • }
  • if (arg->untrust) {
  • OBJ_UNTRUST(arg->str);
  • }
    }

/*
@@ -922,8 +916,7 @@ marshal_dump(int argc, VALUE *argv)
arg->dest = 0;
arg->symbols = st_init_numtable();
arg->data = st_init_numtable();

  • arg->taint = FALSE;
  • arg->untrust = FALSE;
  • arg->infection = 0;
    arg->compat_tbl = st_init_numtable();
    arg->encodings = 0;
    arg->str = rb_str_buf_new(0);
    @@ -962,9 +955,8 @@ struct load_arg {
    st_table *symbols;
    st_table *data;
    VALUE proc;
  • int taint;
  • int untrust;
    st_table *compat_tbl;
  • int infection;
    };

static void
@@ -1118,8 +1110,7 @@ r_bytes0(long len, struct load_arg *arg)
if (NIL_P(str)) goto too_short;
StringValue(str);
if (RSTRING_LEN(str) != len) goto too_short;

  • if (OBJ_TAINTED(str)) arg->taint = TRUE;
  • if (OBJ_UNTRUSTED(str)) arg->untrust = TRUE;
  • arg->infection |= FL_TEST(str, MARSHAL_INFECTION);
    }
    return str;
    }
    @@ -1220,15 +1211,10 @@ r_entry0(VALUE v, st_index_t num, struct
    load_arg *arg)
    else {
    st_insert(arg->data, num, (st_data_t)v);
    }
  • if (arg->taint) {
  •    OBJ_TAINT(v);
    
  •    if ((VALUE)real_obj != Qundef)
    
  •        OBJ_TAINT((VALUE)real_obj);
    
  • }
  • if (arg->untrust) {
  •    OBJ_UNTRUST(v);
    
  •    if ((VALUE)real_obj != Qundef)
    
  •        OBJ_UNTRUST((VALUE)real_obj);
    
  • if (arg->infection) {
  • FL_SET(v, arg->infection);
  • if ((VALUE)real_obj != Qundef)
  •  FL_SET((VALUE)real_obj, arg->infection);
    
    }
    return v;
    }
    @@ -1765,7 +1751,7 @@ static VALUE
    marshal_load(int argc, VALUE *argv)
    {
    VALUE port, proc;
  • int major, minor, taint = FALSE;
  • int major, minor, infection = 0;
    VALUE v;
    volatile VALUE wrapper;
    struct load_arg *arg;
    @@ -1773,21 +1759,20 @@ marshal_load(int argc, VALUE *argv)
    rb_scan_args(argc, argv, “11”, &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
  • taint = OBJ_TAINTED(port); /* original taintedness */
  • infection = FL_TEST(port, MARSHAL_INFECTION); /* original taintedness
    */
    port = v;
    }
    else if (rb_respond_to(port, s_getbyte) && rb_respond_to(port,
    s_read)) {
    if (rb_respond_to(port, s_binmode)) {
    rb_funcall2(port, s_binmode, 0, 0);
    }
  • taint = TRUE;
  • infection = FL_TAINT | FL_TEST(port, FL_UNTRUSTED);;
    }
    else {
    rb_raise(rb_eTypeError, “instance of IO needed”);
    }
    wrapper = TypedData_Make_Struct(rb_cData, struct load_arg,
    &load_arg_data, arg);
  • arg->taint = taint;
  • arg->untrust = OBJ_UNTRUSTED(port);
  • arg->infection = infection;
    arg->src = port;
    arg->offset = 0;
    arg->symbols = st_init_numtable();

e$B6a1J$H?=$7$^$9!#e(B

dfreee$B4X?t$N8F$S=P$7Cf$K%%V%8%’%/%H$N3d$jEv$F$r$9$k3HD%%i%$%V%ie(B
e$B%j$,$"$C$?$N$G!“e(Bmark phasee$B$HJ,N%$7$?$s$G$7$?!#e(B
e$B$J$k$[$I!”$=$&$$$&M}M3$G$7$?$+!#e(B
README.EXT(.ja) e$B$K$Oe(B mark/free e$B4X?t$+$ie(B Ruby
e$B$N%
%V%8%’%/%H$re(B
e$B3NJ]$7$A$c$@$a$H5-:$5$l$F$^$9$,!"$=$N@)8B$O<h$j$O$i$o$l$F$$$k$s$G$9$M!#e(B

e$B$D$$$G$K!“e(BTAINTEDe$B$He(BUNTRUSTEDe$B$r$R$H$^$H$a$K07$&$h$&$K$7$F$_$^$7$?!#e(B
e$B$3$l$G$I$&$G$7$g$&!#e(B
e$B$”$j$,$H$&$4$6$$$^$9!#e(B
e$BG0$N$?$a<j85$G$3$A$i$N%Q%C%A$r$"$F$?$b$N$be(B gc_sweep(): unknown
data type e$B$,e(B
e$BH/@8$7$J$$$3$H$r3NG’CW$7$^$7$?!#e(B

Chikanaga Tomoyuki
Nippon Control System Corp.