merge revision(s) 38364,38366: [Backport #7557]

* object.c (Init_Object): use rb_mod_init_copy for Class#initialize_copy

	* class.c (rb_class_init_copy): rename to class_init_copy_check, performs type
	  checks on arguments to prevent reinitialization of initialized class
	  [ruby-core:50869] [Bug #7557]

	* class.c (rb_mod_init_copy): use class_init_copy_check if receiver is T_CLASS

	* test/ruby/test_class.rb (class TestClass): related test


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@38507 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
usa 2012-12-20 10:03:54 +00:00
parent 74bca55da9
commit 272dd5c6b7
5 changed files with 42 additions and 18 deletions

View file

@ -1,3 +1,12 @@
Thu Dec 13 23:10:52 Charlie Somerville <charlie@charliesomerville.com>
* object.c (Init_Object): use rb_mod_init_copy for Class#initialize_copy
* class.c (rb_class_init_copy): rename to class_init_copy_check, performs type
checks on arguments to prevent reinitialization of initialized class
[ruby-core:50869] [Bug #7557]
* class.c (rb_mod_init_copy): use class_init_copy_check if receiver is T_CLASS
* test/ruby/test_class.rb (class TestClass): related test
Thu Dec 20 18:46:17 2012 Naohisa Goto <ngotogenome@gmail.com> Thu Dec 20 18:46:17 2012 Naohisa Goto <ngotogenome@gmail.com>
* test/dl/test_func.rb (test_name_with_block, test_bind, test_qsort1): * test/dl/test_func.rb (test_name_with_block, test_bind, test_qsort1):

33
class.c
View file

@ -159,10 +159,27 @@ clone_const_i(st_data_t key, st_data_t value, st_data_t data)
return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data);
} }
static void
class_init_copy_check(VALUE clone, VALUE orig)
{
if (orig == rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't copy the root class");
}
if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
rb_raise(rb_eTypeError, "already initialized class");
}
if (FL_TEST(orig, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "can't copy singleton class");
}
}
/* :nodoc: */ /* :nodoc: */
VALUE VALUE
rb_mod_init_copy(VALUE clone, VALUE orig) rb_mod_init_copy(VALUE clone, VALUE orig)
{ {
if (RB_TYPE_P(clone, T_CLASS)) {
class_init_copy_check(clone, orig);
}
rb_obj_init_copy(clone, orig); rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
RBASIC(clone)->klass = rb_singleton_class_clone(orig); RBASIC(clone)->klass = rb_singleton_class_clone(orig);
@ -203,22 +220,6 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
return clone; return clone;
} }
/* :nodoc: */
VALUE
rb_class_init_copy(VALUE clone, VALUE orig)
{
if (orig == rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't copy the root class");
}
if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
rb_raise(rb_eTypeError, "already initialized class");
}
if (FL_TEST(orig, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "can't copy singleton class");
}
return rb_mod_init_copy(clone, orig);
}
VALUE VALUE
rb_singleton_class_clone(VALUE obj) rb_singleton_class_clone(VALUE obj)
{ {

View file

@ -2791,7 +2791,6 @@ Init_Object(void)
rb_define_method(rb_cClass, "allocate", rb_obj_alloc, 0); rb_define_method(rb_cClass, "allocate", rb_obj_alloc, 0);
rb_define_method(rb_cClass, "new", rb_class_new_instance, -1); rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1); rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0); rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
rb_define_alloc_func(rb_cClass, rb_class_s_alloc); rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
rb_undef_method(rb_cClass, "extend_object"); rb_undef_method(rb_cClass, "extend_object");

View file

@ -258,4 +258,19 @@ class TestClass < Test::Unit::TestCase
END END
assert_equal(42, PrivateClass.new.foo) assert_equal(42, PrivateClass.new.foo)
end end
def test_cannot_reinitialize_class_with_initialize_copy # [ruby-core:50869]
assert_in_out_err([], <<-RUBY, ["Object"], [])
class Class
def initialize_copy(*); super; end
end
class A; end
class B; end
A.send(:initialize_copy, Class.new(B)) rescue nil
p A.superclass
RUBY
end
end end

View file

@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.3" #define RUBY_VERSION "1.9.3"
#define RUBY_PATCHLEVEL 353 #define RUBY_PATCHLEVEL 354
#define RUBY_RELEASE_DATE "2012-12-20" #define RUBY_RELEASE_DATE "2012-12-20"
#define RUBY_RELEASE_YEAR 2012 #define RUBY_RELEASE_YEAR 2012