diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-04-22 08:09:44 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-04-22 08:09:44 +0000 |
commit | 67b180748b7e8e551f46a072013162db83ac703f (patch) | |
tree | da0c62f118ff38fb0a5e7992c4c06f409584b47d | |
parent | 16dc6c29554d9ea0cc3c01592646cceec827bba3 (diff) | |
download | ruby-67b180748b7e8e551f46a072013162db83ac703f.tar.gz |
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]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40408 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | marshal.c | 45 | ||||
-rw-r--r-- | test/ruby/test_marshal.rb | 28 |
3 files changed, 64 insertions, 14 deletions
@@ -1,3 +1,8 @@ +Mon Apr 22 17:09:37 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * 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@ruby-lang.org> * util.c (ruby_hdtoa): revert r29729. @@ -1335,7 +1335,7 @@ r_entry0(VALUE v, st_index_t num, struct load_arg *arg) } 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) 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) 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, VALUE extmod) 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, VALUE extmod) 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, VALUE extmod) 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); diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index a642385a8e..d7afec3f66 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -538,16 +538,23 @@ class TestMarshal < Test::Unit::TestCase 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 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")} |