diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-12-22 13:15:58 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-12-22 13:15:58 +0000 |
commit | 96ac47c25109abfd846eb45ae6cb6b56c8b178e3 (patch) | |
tree | 23a6763c57b782d374aa8a02deba2a4a7aabd7f6 | |
parent | 3f90a4ae1e5a6c3dcf83ece419019a1797caed04 (diff) |
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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53243 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | class.c | 15 | ||||
-rw-r--r-- | gc.c | 6 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | test/ruby/test_class.rb | 20 | ||||
-rw-r--r-- | test/ruby/test_objectspace.rb | 7 |
6 files changed, 56 insertions, 1 deletions
@@ -1,3 +1,11 @@ +Tue Dec 22 22:15:53 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * 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@ruby-lang.org> * ext/io/console/io-console.gemspec: bump up to 0.4.4. @@ -442,6 +442,19 @@ rb_singleton_class_attached(VALUE klass, VALUE obj) */ #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, VALUE obj) */ #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. @@ -2400,6 +2400,12 @@ internal_object_p(VALUE obj) 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; diff --git a/internal.h b/internal.h index 142f14dc39..83a7d051ac 100644 --- a/internal.h +++ b/internal.h @@ -491,6 +491,7 @@ struct RClass { 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) diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb index e60db37c15..81c11e6f88 100644 --- a/test/ruby/test_class.rb +++ b/test/ruby/test_class.rb @@ -556,4 +556,24 @@ class TestClass < Test::Unit::TestCase } 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 diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index b701e0fc91..ec561bc405 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -149,5 +149,12 @@ End } 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 |