From c2dcc9045ff3019ed90a37f8628fb8a4b0235e18 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 2 Dec 2015 07:27:22 +0000 Subject: 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 --- ChangeLog | 14 ++++++++++++++ encoding.c | 19 ++++++++++++++++++- internal.h | 1 + marshal.c | 17 +++++++++++++++-- object.c | 10 ++++++++-- test/ruby/test_encoding.rb | 3 +++ 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 + + * 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 * configure.in: Fixed double negative comments. diff --git a/encoding.c b/encoding.c index 5b9f2a0331..fe720767c2 100644 --- a/encoding.c +++ b/encoding.c @@ -1264,6 +1264,14 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2) return rb_enc_from_encoding(enc); } +/* :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) @@ -1275,6 +1283,13 @@ enc_dump(int argc, VALUE *argv, VALUE self) /* :nodoc: */ 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 -- cgit v1.2.3