[#28687] [Bug #2973] rb_bug - Segmentation fault - error.c:213 — rudolf gavlas <redmine@...>

Bug #2973: rb_bug - Segmentation fault - error.c:213

10 messages 2010/03/16

[#28735] [Bug #2982] Ruby tries to link with both openssl and readline — Lucas Nussbaum <redmine@...>

Bug #2982: Ruby tries to link with both openssl and readline

16 messages 2010/03/18

[#28736] [Bug #2983] Ruby (GPLv2 only) tries to link to with readline (now GPLv3) — Lucas Nussbaum <redmine@...>

Bug #2983: Ruby (GPLv2 only) tries to link to with readline (now GPLv3)

10 messages 2010/03/18

[#28907] [Bug #3000] Open SSL Segfaults — Christian Höltje <redmine@...>

Bug #3000: Open SSL Segfaults

19 messages 2010/03/23

[#28924] [Bug #3005] Ruby core dump - [BUG] rb_sys_fail() - errno == 0 — Sebastian YEPES <redmine@...>

Bug #3005: Ruby core dump - [BUG] rb_sys_fail() - errno == 0

10 messages 2010/03/24

[#28954] [Feature #3010] slow require gems in ruby 1.9.1 — Miao Jiang <redmine@...>

Feature #3010: slow require gems in ruby 1.9.1

15 messages 2010/03/24

[#29179] [Bug #3071] Convert rubygems and rdoc to use psych — Aaron Patterson <redmine@...>

Bug #3071: Convert rubygems and rdoc to use psych

10 messages 2010/03/31

[ruby-core:28719] [Feature #2740] Extend const_missing to pass in the nesting

From: Yusuke Endoh <redmine@...>
Date: 2010-03-17 17:00:18 UTC
List: ruby-core #28719
Issue #2740 has been updated by Yusuke Endoh.


Hi,

Matz, do you accept Yehuda's suggestion?

Current status:

- Three persons (nobu, murphy and I) have approved.
- There is no objection.
- There is a patch written by nobu and murphy, though it has a
  little bug.  I revised a patch below.


2010/2/15 Yehuda Katz <redmine@ruby-lang.org>:
>    class Module
>      def const_missing(name)
>        puts "#{self} is missing #{name}"
>        raise NoConstantError unless self == Object
>      end
>    end
>
*snip
>
>    module Foo::Bar
>      Foo::Bar::Baz
>    end
>
>    # Output
>    # Foo::Bar is missing Baz


I'd like to make sure one thing; the above code should raise
NoConstantError after the output, ok?  This is because scoped
constant reference does not check bindings of Object class.

Instead of raising an error, nobu's patch leaks Qundef for the
above code, which causes SEGV in RubySpec.  It is clearly a
problem.


diff --git a/error.c b/error.c
index 3fcd184..d0373fd 100644
--- a/error.c
+++ b/error.c
@@ -401,6 +401,8 @@ VALUE rb_eScriptError;
 VALUE rb_eSyntaxError;
 VALUE rb_eLoadError;
 
+VALUE rb_eNoConstantError;
+
 VALUE rb_eSystemCallError;
 VALUE rb_mErrno;
 static VALUE rb_eNOERROR;
@@ -701,18 +703,34 @@ exit_success_p(VALUE exc)
     return Qfalse;
 }
 
+static VALUE
+new_name_error(VALUE klass, ID id, const char *fmt, va_list args)
+{
+    VALUE argv[2];
+    argv[0] = rb_vsprintf(fmt, args);
+    argv[1] = ID2SYM(id);
+    return rb_class_new_instance(2, argv, klass);
+}
+
 void
 rb_name_error(ID id, const char *fmt, ...)
 {
-    VALUE exc, argv[2];
+    VALUE exc;
     va_list args;
-
     va_start(args, fmt);
-    argv[0] = rb_vsprintf(fmt, args);
+    exc = new_name_error(rb_eNameError, id, fmt, args);
     va_end(args);
+    rb_exc_raise(exc);
+}
 
-    argv[1] = ID2SYM(id);
-    exc = rb_class_new_instance(2, argv, rb_eNameError);
+void
+rb_name_error_with_class(VALUE klass, ID id, const char *fmt, ...)
+{
+    VALUE exc;
+    va_list args;
+    va_start(args, fmt);
+    exc = new_name_error(klass, id, fmt, args);
+    va_end(args);
     rb_exc_raise(exc);
 }
 
@@ -1142,6 +1160,7 @@ Init_Exception(void)
     rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
     rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
     rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
+    rb_eNoConstantError = rb_define_class("NoConstantError", rb_eNameError);
 
     rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
     rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
diff --git a/test/rake/test_top_level_functions.rb b/test/rake/test_top_level_functions.rb
index 12a8cd1..7315f88 100644
--- a/test/rake/test_top_level_functions.rb
+++ b/test/rake/test_top_level_functions.rb
@@ -86,6 +86,6 @@ class Rake::TestTopLevelFunctions < Test::Unit::TestCase
   end
 
   def test_missing_other_constant
-    assert_raise(NameError) do Object.const_missing(:Xyz) end
+    assert_raise(NoConstantError) do Object.const_missing(:Xyz) end
   end
 end
diff --git a/test/ruby/test_basicinstructions.rb b/test/ruby/test_basicinstructions.rb
index ff14e4a..eb985ef 100644
--- a/test/ruby/test_basicinstructions.rb
+++ b/test/ruby/test_basicinstructions.rb
@@ -271,25 +271,25 @@ class TestBasicInstructions < Test::Unit::TestCase
     Const::A::B._remove_const :C
     assert_equal 'Const::C', Const::C
     assert_equal 'Const::A::C', Const::A::C
-    assert_raise(NameError) { Const::A::B::C }
+    assert_raise(NoConstantError) { Const::A::B::C }
 
     Const::A._remove_const :C
     assert_equal 'Const::C', Const::C
-    assert_raise(NameError) { Const::A::C }
-    assert_raise(NameError) { Const::A::B::C }
+    assert_raise(NoConstantError) { Const::A::C }
+    assert_raise(NoConstantError) { Const::A::B::C }
 
     Const._remove_const :C
-    assert_raise(NameError) { Const::C }
-    assert_raise(NameError) { Const::A::C }
-    assert_raise(NameError) { Const::A::B::C }
+    assert_raise(NoConstantError) { Const::C }
+    assert_raise(NoConstantError) { Const::A::C }
+    assert_raise(NoConstantError) { Const::A::B::C }
 
     Const::A.const_set :C, 'Const::A::C'
-    assert_raise(NameError) { Const::C }
+    assert_raise(NoConstantError) { Const::C }
     assert_equal 'Const::A::C', Const::A::C
-    assert_raise(NameError) { Const::A::B::C }
+    assert_raise(NoConstantError) { Const::A::B::C }
 
     Const::A::B.const_set :C, 'Const::A::B::C'
-    assert_raise(NameError) { Const::C }
+    assert_raise(NoConstantError) { Const::C }
     assert_equal 'Const::A::C', Const::A::C
     assert_equal 'Const::A::B::C', Const::A::B::C
 
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index f905431..fbeb29b 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -451,13 +451,13 @@ class TestModule < Test::Unit::TestCase
     assert_equal(:foo, c1::Foo)
     assert_equal(:foo, c2::Foo)
     assert_equal(:foo, c2.const_get(:Foo))
-    assert_raise(NameError) { c2.const_get(:Foo, false) }
+    assert_raise(NoConstantError) { c2.const_get(:Foo, false) }
 
     eval("c1::Foo = :foo")
-    assert_raise(NameError) { c1::Bar }
-    assert_raise(NameError) { c2::Bar }
-    assert_raise(NameError) { c2.const_get(:Bar) }
-    assert_raise(NameError) { c2.const_get(:Bar, false) }
+    assert_raise(NoConstantError) { c1::Bar }
+    assert_raise(NoConstantError) { c2::Bar }
+    assert_raise(NoConstantError) { c2.const_get(:Bar) }
+    assert_raise(NoConstantError) { c2.const_get(:Bar, false) }
 
     c1.instance_eval do
       def const_missing(x)
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 0a49422..af91f75 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -437,7 +437,7 @@ class TestObject < Test::Unit::TestCase
     x = "foo".instance_exec("bar") {|a| self + a }
     assert_equal("foobar", x)
 
-    assert_raise(NameError) do
+    assert_raise(NoConstantError) do
       InstanceExec.new.instance_exec { INSTANCE_EXEC }
     end
   end
diff --git a/variable.c b/variable.c
index d7b99f1..4be8a8e 100644
--- a/variable.c
+++ b/variable.c
@@ -1341,23 +1341,49 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
     return Qnil;		/* not reached */
 }
 
+extern VALUE rb_eNoConstantError;
+
+PRINTF_ARGS(NORETURN(void rb_name_error_with_class(VALUE, ID, const char*, ...)), 3, 4);
 NORETURN(static void uninitialized_constant(VALUE, ID));
 static void
 uninitialized_constant(VALUE klass, ID id)
 {
-    if (klass && klass != rb_cObject)
-	rb_name_error(id, "uninitialized constant %s::%s",
+    if (klass && klass != rb_cObject){
+	rb_name_error_with_class(rb_eNoConstantError,
+		      id, "uninitialized constant %s::%s",
 		      rb_class2name(klass),
 		      rb_id2name(id));
+    }
     else {
-	rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
+	rb_name_error_with_class(rb_eNoConstantError,
+		      id, "uninitialized constant %s", rb_id2name(id));
     }
 }
 
 static VALUE
+const_missing_call(VALUE arg)
+{
+    VALUE *args = (VALUE *)arg;
+    ID const_missing_id;
+    CONST_ID(const_missing_id, "const_missing");
+    return rb_check_funcall(args[0], const_missing_id, 1, &args[1]);
+}
+
+static VALUE
+const_missing_rescue(VALUE arg, VALUE errinfo)
+{
+    return arg;
+}
+
+static VALUE
 const_missing(VALUE klass, ID id)
 {
-    return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
+    VALUE args[2];
+    args[0] = klass;
+    args[1] = ID2SYM(id);
+    return rb_rescue2(const_missing_call, (VALUE)args,
+		      const_missing_rescue, (VALUE)Qundef,
+		      rb_eNoConstantError, (VALUE)0);
 }
 
 
@@ -1597,7 +1623,27 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
 	goto retry;
     }
 
-    value = const_missing(klass, id);
+    tmp = klass;
+    if ((value = const_missing(tmp, id)) == Qundef) {
+	NODE *rb_vm_cref(void);
+	NODE *cref = rb_vm_cref();
+	cref = cref->nd_next;
+	while (cref && cref->nd_next &&
+	       ((cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) ||
+		NIL_P(tmp = cref->nd_clss) ||
+		(value = const_missing(tmp, id)) == Qundef)) {
+	    cref = cref->nd_next;
+	}
+	if (value == Qundef) {
+	    if (!exclude) {
+		value = const_missing(rb_cObject, id);
+	    }
+	    if (value == Qundef) {
+		uninitialized_constant(klass, id);
+	    }
+	}
+    }
+
     rb_vm_inc_const_missing_count();
     return value;
 }
@@ -1655,7 +1701,7 @@ rb_const_remove(VALUE mod, ID id)
 	    rb_name_error(id, "cannot remove %s::%s",
 			  rb_class2name(mod), rb_id2name(id));
 	}
-	rb_name_error(id, "constant %s::%s not defined",
+	rb_name_error_with_class(rb_eNoConstantError, id, "constant %s::%s not defined",
 		      rb_class2name(mod), rb_id2name(id));
     }
 

-- 
Yusuke ENDOH <mame@tsg.ne.jp>
----------------------------------------
http://redmine.ruby-lang.org/issues/show/2740

----------------------------------------
http://redmine.ruby-lang.org

In This Thread

Prev Next