From 628e432739e1d2578d357420aa652a97eb8c2649 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 19 Apr 2023 11:40:16 +0900 Subject: [PATCH] fix `NameError` message The following code produces two NameErrors respectively and they are independent, but the second one can show `private constant` message because of first NameError. ```ruby class C class PrivateClass; end private_constant :PrivateClass end begin eval('class C::PrivateClass; end') rescue => e p e end begin Object.const_get 'Foo' rescue => e p e end # # #=> should be # ``` It fails the test-all tests with `make test-all TESTS='ruby/class ruby/parse --seed=58891 -v`. The reason is clear miss from https://github.com/ruby/ruby/commit/7387c08373a --- test/ruby/test_class.rb | 11 +++++++++++ variable.c | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb index 5086e60398..d1d196c9af 100644 --- a/test/ruby/test_class.rb +++ b/test/ruby/test_class.rb @@ -355,6 +355,17 @@ class TestClass < Test::Unit::TestCase assert_equal(42, PrivateClass.new.foo) end + def test_private_const_access + assert_raise_with_message NameError, /uninitialized/ do + begin + eval('class ::TestClass::PrivateClass; end') + rescue NameError => e + end + + Object.const_get "NOT_AVAILABLE_CONST_NAME_#{__LINE__}" + end + end + StrClone = String.clone Class.new(StrClone) diff --git a/variable.c b/variable.c index 39568db24a..e8a66b0c36 100644 --- a/variable.c +++ b/variable.c @@ -2073,11 +2073,12 @@ rb_const_missing(VALUE klass, VALUE name) VALUE rb_mod_const_missing(VALUE klass, VALUE name) { - VALUE ref = GET_EC()->private_const_reference; + rb_execution_context_t *ec = GET_EC(); + VALUE ref = ec->private_const_reference; rb_vm_pop_cfunc_frame(); if (ref) { - rb_name_err_raise("private constant %2$s::%1$s referenced", - ref, name); + ec->private_const_reference = 0; + rb_name_err_raise("private constant %2$s::%1$s referenced", ref, name); } uninitialized_constant(klass, name);