ruby-changes:28356
From: nobu <ko1@a...>
Date: Mon, 22 Apr 2013 17:09:58 +0900 (JST)
Subject: [ruby-changes:28356] nobu:r40408 (trunk): marshal.c: fix marshal_load ivar
nobu 2013-04-22 17:09:44 +0900 (Mon, 22 Apr 2013) New Revision: 40408 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40408 Log: marshal.c: fix marshal_load ivar * marshal.c (r_object0): copy all instance variables not only generic ivars, before calling post proc. [ruby-core:51163] [Bug #7627] Modified files: trunk/ChangeLog trunk/marshal.c trunk/test/ruby/test_marshal.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 40407) +++ ChangeLog (revision 40408) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Apr 22 17:09:37 2013 Nobuyoshi Nakada <nobu@r...> + + * marshal.c (r_object0): copy all instance variables not only generic + ivars, before calling post proc. [ruby-core:51163] [Bug #7627] + Mon Apr 22 10:25:21 2013 NARUSE, Yui <naruse@r...> * util.c (ruby_hdtoa): revert r29729. Index: marshal.c =================================================================== --- marshal.c (revision 40407) +++ marshal.c (revision 40408) @@ -1335,7 +1335,7 @@ r_entry0(VALUE v, st_index_t num, struct https://github.com/ruby/ruby/blob/trunk/marshal.c#L1335 } static VALUE -r_leave(VALUE v, struct load_arg *arg) +r_fixup_compat(VALUE v, struct load_arg *arg) { st_data_t data; if (st_lookup(arg->compat_tbl, v, &data)) { @@ -1349,6 +1349,12 @@ r_leave(VALUE v, struct load_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1349 st_delete(arg->compat_tbl, &key, 0); v = real_obj; } + return v; +} + +static VALUE +r_post_proc(VALUE v, struct load_arg *arg) +{ if (arg->proc) { v = rb_funcall(arg->proc, s_call, 1, v); check_load_arg(arg, s_call); @@ -1356,6 +1362,28 @@ r_leave(VALUE v, struct load_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1362 return v; } +static VALUE +r_leave(VALUE v, struct load_arg *arg) +{ + v = r_fixup_compat(v, arg); + v = r_post_proc(v, arg); + return v; +} + +static int +copy_ivar_i(st_data_t key, st_data_t val, st_data_t arg) +{ + rb_ivar_set((VALUE)arg, (ID)key, (VALUE)val); + return ST_CONTINUE; +} + +static VALUE +r_copy_ivar(VALUE v, VALUE data) +{ + rb_ivar_foreach(data, copy_ivar_i, (st_data_t)v); + return v; +} + static void r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg) { @@ -1458,10 +1486,7 @@ r_object0(struct load_arg *arg, int *ivp https://github.com/ruby/ruby/blob/trunk/marshal.c#L1486 rb_raise(rb_eArgError, "dump format error (unlinked)"); } v = (VALUE)link; - if (arg->proc) { - v = rb_funcall(arg->proc, s_call, 1, v); - check_load_arg(arg, s_call); - } + r_post_proc(v, arg); break; case TYPE_IVAR: @@ -1768,7 +1793,6 @@ r_object0(struct load_arg *arg, int *ivp https://github.com/ruby/ruby/blob/trunk/marshal.c#L1793 VALUE klass = path2class(r_unique(arg)); VALUE oldclass = 0; VALUE data; - st_table *ivtbl; v = obj_alloc_by_klass(klass, arg, &oldclass); if (!NIL_P(extmod)) { @@ -1783,12 +1807,9 @@ r_object0(struct load_arg *arg, int *ivp https://github.com/ruby/ruby/blob/trunk/marshal.c#L1807 data = r_object(arg); rb_funcall2(v, s_mload, 1, &data); check_load_arg(arg, s_mload); - v = r_leave(v, arg); - ivtbl = rb_generic_ivar_table(data); - if (ivtbl && ivtbl->num_entries) { - rb_check_frozen(v); - rb_copy_generic_ivar(v, data); - } + v = r_fixup_compat(v, arg); + v = r_copy_ivar(v, data); + v = r_post_proc(v, arg); if (!NIL_P(extmod)) { if (oldclass) append_extmod(v, extmod); rb_ary_clear(extmod); Index: test/ruby/test_marshal.rb =================================================================== --- test/ruby/test_marshal.rb (revision 40407) +++ test/ruby/test_marshal.rb (revision 40408) @@ -538,16 +538,23 @@ class TestMarshal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_marshal.rb#L538 assert_nil(loaded.foo, bug7627) end - class Bug8276 + class LoadData attr_reader :data def initialize(data) @data = data - freeze end alias marshal_dump data alias marshal_load initialize end + class Bug8276 < LoadData + def initialize(*) + super + freeze + end + alias marshal_load initialize + end + def test_marshal_dump_excess_encoding bug8276 = '[ruby-core:54334] [Bug #8276]' t = Bug8276.new(bug8276) @@ -564,6 +571,23 @@ class TestMarshal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_marshal.rb#L571 assert_raise(RuntimeError) {Marshal.load(s)} end + def test_marshal_load_ivar + s = "data with ivar" + s.instance_variable_set(:@t, 42) + t = LoadData.new(s) + s = Marshal.dump(t) + hook = ->(v) { + if LoadData === v + assert_send([v, :instance_variable_defined?, :@t]) + assert_equal(42, v.instance_variable_get(:@t)) + end + v + } + v = Marshal.load(s, hook) + assert_send([v, :instance_variable_defined?, :@t]) + assert_equal(42, v.instance_variable_get(:@t)) + end + def test_class_ivar assert_raise(TypeError) {Marshal.load("\x04\x08Ic\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/