summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-02 07:27:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-02 07:27:22 +0000
commit2a66cc554db6263bc04c804ad62750497c26a772 (patch)
tree4c3eddec025ca9be4434af4d1de4264caa0647cf
parenta497ed37332948baf3433210e46c7bb71dfe33a6 (diff)
encoding.c: defer finding encoding
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52856 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog14
-rw-r--r--encoding.c19
-rw-r--r--internal.h1
-rw-r--r--marshal.c17
-rw-r--r--object.c10
-rw-r--r--test/ruby/test_encoding.rb3
6 files changed, 59 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 73fbb1491f..31ce5bcb42 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Wed Dec 2 16:27:19 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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.
+
Wed Dec 2 15:12:43 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* configure.in: Fixed double negative comments.
diff --git a/encoding.c b/encoding.c
index 5b9f2a0331..fe720767c2 100644
--- a/encoding.c
+++ b/encoding.c
@@ -1266,6 +1266,14 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
/* :nodoc: */
static VALUE
+enc_s_alloc(VALUE klass)
+{
+ rb_undefined_alloc(klass);
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
enc_dump(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 0, 1);
@@ -1276,6 +1284,13 @@ enc_dump(int argc, VALUE *argv, VALUE self)
static VALUE
enc_load(VALUE klass, VALUE str)
{
+ return str;
+}
+
+/* :nodoc: */
+static VALUE
+enc_m_loader(VALUE klass, VALUE str)
+{
return enc_find(klass, str);
}
@@ -1902,7 +1917,7 @@ Init_Encoding(void)
int i;
rb_cEncoding = rb_define_class("Encoding", rb_cObject);
- rb_undef_alloc_func(rb_cEncoding);
+ rb_define_alloc_func(rb_cEncoding, enc_s_alloc);
rb_undef_method(CLASS_OF(rb_cEncoding), "new");
rb_define_method(rb_cEncoding, "to_s", enc_name, 0);
rb_define_method(rb_cEncoding, "inspect", enc_inspect, 0);
@@ -1934,6 +1949,8 @@ Init_Encoding(void)
for (i = 0; i < enc_table.count; ++i) {
rb_ary_push(list, enc_new(enc_table.list[i].enc));
}
+
+ rb_marshal_define_compat(rb_cEncoding, Qnil, NULL, enc_m_loader);
}
/* locale insensitive ctype functions */
diff --git a/internal.h b/internal.h
index d3db0a6104..1018d0bd30 100644
--- a/internal.h
+++ b/internal.h
@@ -969,6 +969,7 @@ rb_float_new_inline(double d)
void rb_obj_copy_ivar(VALUE dest, VALUE obj);
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
+NORETURN(void rb_undefined_alloc(VALUE klass));
double rb_num_to_dbl(VALUE val);
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
diff --git a/marshal.c b/marshal.c
index 74d66a208a..3b7f79d614 100644
--- a/marshal.c
+++ b/marshal.c
@@ -128,6 +128,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))
{
@@ -146,7 +148,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
@@ -1831,6 +1833,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
VALUE name = r_unique(arg);
VALUE klass = path2class(name);
VALUE data;
+ st_data_t d;
if (!rb_obj_respond_to(klass, s_load, TRUE)) {
rb_raise(rb_eTypeError, "class %"PRIsVALUE" needs to have method `_load'",
@@ -1843,7 +1846,11 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
v = load_funcall(arg, klass, s_load, 1, &data);
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;
@@ -2217,13 +2224,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
diff --git a/object.c b/object.c
index 5023f64b0d..ff2db0b45a 100644
--- a/object.c
+++ b/object.c
@@ -1770,6 +1770,13 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass)
return klass;
}
+void
+rb_undefined_alloc(VALUE klass)
+{
+ rb_raise(rb_eTypeError, "allocator undefined for %"PRIsVALUE,
+ klass);
+}
+
/*
* call-seq:
* class.allocate() -> obj
@@ -1806,8 +1813,7 @@ rb_obj_alloc(VALUE klass)
}
allocator = rb_get_alloc_func(klass);
if (!allocator) {
- rb_raise(rb_eTypeError, "allocator undefined for %"PRIsVALUE,
- klass);
+ rb_undefined_alloc(klass);
}
RUBY_DTRACE_CREATE_HOOK(OBJECT, rb_class2name(klass));
diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb
index 63c56e2cd3..abe4317ff6 100644
--- a/test/ruby/test_encoding.rb
+++ b/test/ruby/test_encoding.rb
@@ -33,6 +33,9 @@ class TestEncoding < Test::Unit::TestCase
assert_raise(TypeError) { e.dup }
assert_raise(TypeError) { e.clone }
assert_equal(e.object_id, Marshal.load(Marshal.dump(e)).object_id)
+ assert_not_predicate(e, :tainted?)
+ Marshal.load(Marshal.dump(e).taint)
+ assert_not_predicate(e, :tainted?, '[ruby-core:71793] [Bug #11760]')
end
end