summaryrefslogtreecommitdiff
path: root/marshal.c
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-08 16:44:45 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-08 16:44:45 +0000
commitbd4364acb13fbf03e80dcf83a5e3b5d29410b0cc (patch)
tree32aa7ac9cad525d376ae05aa600ba774b6960bc9 /marshal.c
parent4cd4556f95530fce4fcd61387c3b45aaf6c2c44a (diff)
merge revision(s) 52856,52906: [Backport #11760]
* encoding.c (enc_m_loader): defer finding encoding object not to be infected by marshal source. [ruby-core:71793] [Bug #11760] * marshal.c (r_object0): enable compatible loader on USERDEF class. the loader function is called with the class itself, instead of an allocated object, and the loaded data. * marshal.c (compat_allocator_table): intialize compat_allocator_tbl on demand. * object.c (rb_undefined_alloc): extract from rb_obj_alloc. * marshal.c (compat_allocator_table): initialize git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@52974 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'marshal.c')
-rw-r--r--marshal.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/marshal.c b/marshal.c
index ab1ab56408..557a2c21a2 100644
--- a/marshal.c
+++ b/marshal.c
@@ -124,6 +124,8 @@ mark_marshal_compat_t(void *tbl)
st_foreach(tbl, mark_marshal_compat_i, 0);
}
+static st_table *compat_allocator_table(void);
+
void
rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE))
{
@@ -142,7 +144,7 @@ rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE),
compat->dumper = dumper;
compat->loader = loader;
- st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat);
+ st_insert(compat_allocator_table(), (st_data_t)allocator, (st_data_t)compat);
}
#define MARSHAL_INFECTION FL_TAINT
@@ -1820,6 +1822,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
{
VALUE klass = path2class(r_unique(arg));
VALUE data;
+ st_data_t d;
if (!rb_obj_respond_to(klass, s_load, TRUE)) {
rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
@@ -1833,7 +1836,11 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = rb_funcall2(klass, s_load, 1, &data);
check_load_arg(arg, s_load);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ if (st_lookup(compat_allocator_tbl, (st_data_t)rb_get_alloc_func(klass), &d)) {
+ marshal_compat_t *compat = (marshal_compat_t*)d;
+ v = compat->loader(klass, v);
+ }
+ v = r_post_proc(v, arg);
}
break;
@@ -2198,13 +2205,19 @@ Init_marshal(void)
rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
/* minor version */
rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
+}
+static st_table *
+compat_allocator_table(void)
+{
+ if (compat_allocator_tbl) return compat_allocator_tbl;
compat_allocator_tbl = st_init_numtable();
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
compat_allocator_tbl_wrapper =
Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, compat_allocator_tbl);
rb_gc_register_mark_object(compat_allocator_tbl_wrapper);
+ return compat_allocator_tbl;
}
VALUE