summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ruby/test_module.rb26
-rw-r--r--vm.c2
-rw-r--r--vm_method.c4
3 files changed, 30 insertions, 2 deletions
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 37045ad0d9..cf50db3374 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -705,6 +705,32 @@ class TestModule < Test::Unit::TestCase
assert_equal(false, o.respond_to?(:bar=))
end
+ def test_attr_public_at_toplevel
+ s = Object.new
+ TOPLEVEL_BINDING.eval(<<-END).call(s.singleton_class)
+ proc do |c|
+ c.send(:attr_accessor, :x)
+ c.send(:attr, :y)
+ c.send(:attr_reader, :z)
+ c.send(:attr_writer, :w)
+ end
+ END
+ assert_nil s.x
+ s.x = 1
+ assert_equal 1, s.x
+
+ assert_nil s.y
+ s.instance_variable_set(:@y, 2)
+ assert_equal 2, s.y
+
+ assert_nil s.z
+ s.instance_variable_set(:@z, 3)
+ assert_equal 3, s.z
+
+ s.w = 4
+ assert_equal 4, s.instance_variable_get(:@w)
+ end
+
def test_const_get_evaled
c1 = Class.new
c2 = Class.new(c1)
diff --git a/vm.c b/vm.c
index 593540a32e..b4e2e3c5e6 100644
--- a/vm.c
+++ b/vm.c
@@ -1383,7 +1383,7 @@ rb_vm_cref_in_context(VALUE self, VALUE cbase)
const rb_execution_context_t *ec = GET_EC();
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
const rb_cref_t *cref;
- if (cfp->self != self) return NULL;
+ if (!cfp || cfp->self != self) return NULL;
if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
cref = vm_get_cref(cfp->ep);
if (CREF_CLASS(cref) != cbase) return NULL;
diff --git a/vm_method.c b/vm_method.c
index 35634d275c..da891229f8 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -1135,14 +1135,16 @@ rb_scope_module_func_set(void)
vm_cref_set_visibility(METHOD_VISI_PRIVATE, TRUE);
}
+const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
void
rb_attr(VALUE klass, ID id, int read, int write, int ex)
{
ID attriv;
rb_method_visibility_t visi;
const rb_execution_context_t *ec = GET_EC();
+ const rb_cref_t *cref = rb_vm_cref_in_context(klass, klass);
- if (!ex) {
+ if (!ex || !cref) {
visi = METHOD_VISI_PUBLIC;
}
else {