ruby-changes:41170
From: nobu <ko1@a...>
Date: Tue, 22 Dec 2015 22:16:06 +0900 (JST)
Subject: [ruby-changes:41170] nobu:r53243 (trunk): gc.c: do not expose internal singleton class
nobu 2015-12-22 22:15:58 +0900 (Tue, 22 Dec 2015) New Revision: 53243 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53243 Log: gc.c: do not expose internal singleton class * gc.c (internal_object_p): should not expose singleton classes without a metaclass. based on patches by ko1 and shugo. [Bug #11740] * class.c (rb_singleton_class_object_p): added. Modified files: trunk/ChangeLog trunk/class.c trunk/gc.c trunk/internal.h trunk/test/ruby/test_class.rb trunk/test/ruby/test_objectspace.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 53242) +++ ChangeLog (revision 53243) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Dec 22 22:15:53 2015 Nobuyoshi Nakada <nobu@r...> + + * gc.c (internal_object_p): should not expose singleton classes + without a metaclass. based on patches by ko1 and shugo. + [Bug #11740] + + * class.c (rb_singleton_class_object_p): added. + Tue Dec 22 22:15:08 2015 Nobuyoshi Nakada <nobu@r...> * ext/io/console/io-console.gemspec: bump up to 0.4.4. Index: gc.c =================================================================== --- gc.c (revision 53242) +++ gc.c (revision 53243) @@ -2400,6 +2400,12 @@ internal_object_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L2400 case T_NODE: case T_ZOMBIE: break; + case T_CLASS: + if (!p->as.basic.klass) break; + if (FL_TEST(obj, FL_SINGLETON)) { + return rb_singleton_class_internal_p(obj); + } + return 0; default: if (!p->as.basic.klass) break; return 0; Index: class.c =================================================================== --- class.c (revision 53242) +++ class.c (revision 53243) @@ -442,6 +442,19 @@ rb_singleton_class_attached(VALUE klass, https://github.com/ruby/ruby/blob/trunk/class.c#L442 */ #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k)) +static int +rb_singleton_class_has_metaclass_p(VALUE sklass) +{ + return rb_attr_get(METACLASS_OF(sklass), id_attached) == sklass; +} + +int +rb_singleton_class_internal_p(VALUE sklass) +{ + return (RB_TYPE_P(rb_attr_get(sklass, id_attached), T_CLASS) && + !rb_singleton_class_has_metaclass_p(sklass)); +} + /*! * whether k has a metaclass * @retval 1 if \a k has a metaclass @@ -449,7 +462,7 @@ rb_singleton_class_attached(VALUE klass, https://github.com/ruby/ruby/blob/trunk/class.c#L462 */ #define HAVE_METACLASS_P(k) \ (FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \ - rb_ivar_get(METACLASS_OF(k), id_attached) == (k)) + rb_singleton_class_has_metaclass_p(k)) /*! * ensures \a klass belongs to its own eigenclass. Index: internal.h =================================================================== --- internal.h (revision 53242) +++ internal.h (revision 53243) @@ -491,6 +491,7 @@ struct RClass { https://github.com/ruby/ruby/blob/trunk/internal.h#L491 void rb_class_subclass_add(VALUE super, VALUE klass); void rb_class_remove_from_super_subclasses(VALUE); +int rb_singleton_class_internal_p(VALUE sklass); #define RCLASS_EXT(c) (RCLASS(c)->ptr) #define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) Index: test/ruby/test_objectspace.rb =================================================================== --- test/ruby/test_objectspace.rb (revision 53242) +++ test/ruby/test_objectspace.rb (revision 53243) @@ -149,5 +149,12 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_objectspace.rb#L149 } assert(exist, 'Bug #11360') End + + klass = Class.new + instance = klass.new + sclass = instance.singleton_class + meta = klass.singleton_class + assert_kind_of(meta, sclass) + assert_include(ObjectSpace.each_object(meta).to_a, sclass) end end Index: test/ruby/test_class.rb =================================================================== --- test/ruby/test_class.rb (revision 53242) +++ test/ruby/test_class.rb (revision 53243) @@ -556,4 +556,24 @@ class TestClass < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_class.rb#L556 } end; end + + def test_should_not_expose_singleton_class_without_metaclass + assert_normal_exit %q{ + klass = Class.new(Array) + # The metaclass of +klass+ should handle #bla since it should inherit methods from meta:meta:Array + def (Array.singleton_class).bla; :bla; end + hidden = ObjectSpace.each_object(Class).find { |c| klass.is_a? c and c.inspect.include? klass.inspect } + raise unless hidden.nil? + }, '[Bug #11740]' + + assert_normal_exit %q{ + klass = Class.new(Array) + klass.singleton_class + # The metaclass of +klass+ should handle #bla since it should inherit methods from meta:meta:Array + def (Array.singleton_class).bla; :bla; end + hidden = ObjectSpace.each_object(Class).find { |c| klass.is_a? c and c.inspect.include? klass.inspect } + raise if hidden.nil? + }, '[Bug #11740]' + + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/