summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-24 07:28:11 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-24 07:28:11 +0000
commit1fc33199736f316dd71d0c551edbf514528ddde6 (patch)
tree41f04b811f87b4439d37b2cd365fda59147ed5ac
parent3c0cbea874a38ee233cae86e1dd854f00d5d6b00 (diff)
proc.c: make method by define_method public
* proc.c (rb_mod_define_method): consider visibility only if self in the caller is same as the receiver, otherwise make public as well as old behavior. [ruby-core:57747] [Bug #9005] [ruby-core:58497] [Bug #9141] * vm.c (rb_vm_cref_in_context): return ruby level cref if self is same. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44380 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog10
-rw-r--r--proc.c9
-rw-r--r--test/ruby/test_method.rb23
-rw-r--r--vm.c9
4 files changed, 50 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index d841621..3e15bfd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Tue Dec 24 16:28:05 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * proc.c (rb_mod_define_method): consider visibility only if self
+ in the caller is same as the receiver, otherwise make public as
+ well as old behavior. [ruby-core:57747] [Bug #9005]
+ [ruby-core:58497] [Bug #9141]
+
+ * vm.c (rb_vm_cref_in_context): return ruby level cref if self is
+ same.
+
Tue Dec 24 14:13:14 2013 Koichi Sasada <ko1@atdot.net>
* README.EXT: add a refer to URL.
diff --git a/proc.c b/proc.c
index 638f22c..f8b2e3b 100644
--- a/proc.c
+++ b/proc.c
@@ -14,6 +14,8 @@
#include "gc.h"
#include "iseq.h"
+NODE *rb_vm_cref_in_context(VALUE self);
+
struct METHOD {
VALUE recv;
VALUE rclass;
@@ -1619,7 +1621,12 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
ID id;
VALUE body;
- int noex = (int)rb_vm_cref()->nd_visi;
+ int noex = NOEX_PUBLIC;
+ const NODE *cref = rb_vm_cref_in_context(mod);
+
+ if (cref && cref->nd_clss == mod) {
+ noex = (int)cref->nd_visi;
+ }
if (argc == 1) {
id = rb_to_id(argv[0]);
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 2fde505..5b7c76d 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -338,6 +338,29 @@ class TestMethod < Test::Unit::TestCase
assert_equal(true, m.private_method_defined?(:foo))
end
+ def test_define_method_in_private_scope
+ bug9005 = '[ruby-core:57747] [Bug #9005]'
+ c = Class.new
+ class << c
+ public :define_method
+ end
+ TOPLEVEL_BINDING.eval("proc{|c|c.define_method(:x) {|*x|throw x}}").call(c)
+ o = c.new
+ assert_throw(bug9005) {o.x(bug9005)}
+ end
+
+ def test_singleton_define_method_in_private_scope
+ bug9141 = '[ruby-core:58497] [Bug #9141]'
+ o = Object.new
+ class << o
+ public :define_singleton_method
+ end
+ TOPLEVEL_BINDING.eval("proc{|o|o.define_singleton_method(:x) {|x|throw x}}").call(o)
+ assert_throw(bug9141) do
+ o.x(bug9141)
+ end
+ end
+
def test_super_in_proc_from_define_method
c1 = Class.new {
def m
diff --git a/vm.c b/vm.c
index e1c6298..947b181 100644
--- a/vm.c
+++ b/vm.c
@@ -930,6 +930,15 @@ rb_vm_cref(void)
return rb_vm_get_cref(cfp->iseq, cfp->ep);
}
+NODE *
+rb_vm_cref_in_context(VALUE self)
+{
+ rb_thread_t *th = GET_THREAD();
+ const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
+ if (cfp->self != self) return NULL;
+ return rb_vm_get_cref(cfp->iseq, cfp->ep);
+}
+
#if 0
void
debug_cref(NODE *cref)