diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | class.c | 9 | ||||
-rw-r--r-- | test/ruby/test_symbol.rb | 29 | ||||
-rw-r--r-- | vm_eval.c | 32 |
4 files changed, 56 insertions, 20 deletions
@@ -1,3 +1,9 @@ +Thu Apr 23 11:35:55 2015 Nobuyoshi Nakada <[email protected]> + + * vm_eval.c (rb_obj_instance_eval, rb_obj_instance_exec): allow + symbols to just instance_eval/exec, execept for definition of + singletons. [ruby-core:68961] [Bug #11086] + Thu Apr 23 10:01:36 2015 SHIBATA Hiroshi <[email protected]> * lib/delegate.rb: fix a typo. @@ -1539,7 +1539,8 @@ singleton_class_of(VALUE obj) { VALUE klass; - if (FIXNUM_P(obj) || FLONUM_P(obj) || SYMBOL_P(obj)) { + if (FIXNUM_P(obj) || FLONUM_P(obj) || STATIC_SYM_P(obj)) { + no_singleton: rb_raise(rb_eTypeError, "can't define singleton"); } if (SPECIAL_CONST_P(obj)) { @@ -1549,9 +1550,9 @@ singleton_class_of(VALUE obj) return klass; } else { - enum ruby_value_type type = BUILTIN_TYPE(obj); - if (type == T_FLOAT || type == T_BIGNUM) { - rb_raise(rb_eTypeError, "can't define singleton"); + switch (BUILTIN_TYPE(obj)) { + case T_FLOAT: case T_BIGNUM: case T_SYMBOL: + goto no_singleton; } } diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 66c62cb298..0a055db2c9 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -199,6 +199,35 @@ class TestSymbol < Test::Unit::TestCase assert_raise(TypeError) { a = :foo; def a.foo; end } end + SymbolsForEval = [ + :foo, + "dynsym_#{Random.rand(10000)}_#{Time.now}".to_sym + ] + + def test_instance_eval + bug11086 = '[ruby-core:68961] [Bug #11086]' + SymbolsForEval.each do |sym| + assert_nothing_raised(TypeError, sym, bug11086) { + sym.instance_eval {} + } + assert_raise(TypeError, sym, bug11086) { + sym.instance_eval {def foo; end} + } + end + end + + def test_instance_exec + bug11086 = '[ruby-core:68961] [Bug #11086]' + SymbolsForEval.each do |sym| + assert_nothing_raised(TypeError, sym, bug11086) { + sym.instance_exec {} + } + assert_raise(TypeError, sym, bug11086) { + sym.instance_exec {def foo; end} + } + end + end + def test_frozen_symbol assert_equal(true, :foo.frozen?) assert_equal(true, :each.frozen?) @@ -1627,6 +1627,20 @@ specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self) } } +static VALUE +singleton_class_for_eval(VALUE self) +{ + if (SPECIAL_CONST_P(self)) { + return rb_special_singleton_class(self); + } + switch (BUILTIN_TYPE(self)) { + case T_FLOAT: case T_BIGNUM: case T_SYMBOL: + return Qnil; + default: + return rb_singleton_class(self); + } +} + /* * call-seq: * obj.instance_eval(string [, filename [, lineno]] ) -> obj @@ -1663,14 +1677,7 @@ specific_eval(int argc, const VALUE *argv, VALUE klass, VALUE self) VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self) { - VALUE klass; - - if (SPECIAL_CONST_P(self)) { - klass = rb_special_singleton_class(self); - } - else { - klass = rb_singleton_class(self); - } + VALUE klass = singleton_class_for_eval(self); return specific_eval(argc, argv, klass, self); } @@ -1695,14 +1702,7 @@ rb_obj_instance_eval(int argc, const VALUE *argv, VALUE self) VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self) { - VALUE klass; - - if (SPECIAL_CONST_P(self)) { - klass = rb_special_singleton_class(self); - } - else { - klass = rb_singleton_class(self); - } + VALUE klass = singleton_class_for_eval(self); return yield_under(klass, self, rb_ary_new4(argc, argv)); } |