[前][次][番号順一覧][スレッド一覧]

ruby-changes:20597

From: nobu <ko1@a...>
Date: Sun, 24 Jul 2011 00:05:15 +0900 (JST)
Subject: [ruby-changes:20597] nobu:r32645 (trunk): * error.c (rb_name_error_str): new function to raise NameError

nobu	2011-07-24 00:05:03 +0900 (Sun, 24 Jul 2011)

  New Revision: 32645

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32645

  Log:
    * error.c (rb_name_error_str): new function to raise NameError
      with the name string but not ID.
    * object.c, proc.c, variable.c: more removal of inadvertent symbol
      creation.  [Feature #5079]

  Modified files:
    trunk/ChangeLog
    trunk/error.c
    trunk/include/ruby/intern.h
    trunk/object.c
    trunk/proc.c
    trunk/test/ruby/test_symbol.rb
    trunk/variable.c

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 32644)
+++ include/ruby/intern.h	(revision 32645)
@@ -209,6 +209,7 @@
 VALUE rb_exc_new3(VALUE, VALUE);
 PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2);
 PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3);
+PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3);
 NORETURN(void rb_invalid_str(const char*, const char*));
 PRINTF_ARGS(void rb_compile_error(const char*, int, const char*, ...), 3, 4);
 PRINTF_ARGS(void rb_compile_error_with_enc(const char*, int, void *, const char*, ...), 4, 5);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 32644)
+++ ChangeLog	(revision 32645)
@@ -1,3 +1,11 @@
+Sun Jul 24 00:05:00 2011  Jeremy Evans  <merch-redmine@j...>
+
+	* error.c (rb_name_error_str): new function to raise NameError
+	  with the name string but not ID.
+
+	* object.c, proc.c, variable.c: more removal of inadvertent symbol
+	  creation.  [Feature #5079]
+
 Sat Jul 23 21:14:00 2011  Tadayoshi Funaba  <tadf@d...>
 
 	* lib/cmath.rb (cbrt): should return a real number if possible.
Index: variable.c
===================================================================
--- variable.c	(revision 32644)
+++ variable.c	(revision 32645)
@@ -1299,7 +1299,7 @@
 rb_obj_remove_instance_variable(VALUE obj, VALUE name)
 {
     VALUE val = Qnil;
-    const ID id = rb_to_id(name);
+    const ID id = rb_check_id(name);
     st_data_t n, v;
     struct st_table *iv_index_tbl;
     st_data_t index;
@@ -1307,6 +1307,14 @@
     if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
 	rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
     rb_check_frozen(obj);
+    if (!id) {
+	if (rb_is_instance_name(name)) {
+	    rb_name_error_str(name, "instance variable %s not defined", RSTRING_PTR(name));
+	}
+	else {
+	    rb_name_error_str(name, "`%s' is not allowed as an instance variable name", RSTRING_PTR(name));
+	}
+    }
     if (!rb_is_instance_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
     }
@@ -1677,8 +1685,17 @@
 VALUE
 rb_mod_remove_const(VALUE mod, VALUE name)
 {
-    const ID id = rb_to_id(name);
+    const ID id = rb_check_id(name);
 
+    if (!id) {
+	if (rb_is_const_name(name)) {
+	    rb_name_error_str(name, "constant %s::%s not defined",
+			      rb_class2name(mod), RSTRING_PTR(name));
+	}
+	else {
+	    rb_name_error_str(name, "`%s' is not allowed as a constant name", RSTRING_PTR(name));
+	}
+    }
     if (!rb_is_const_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
     }
@@ -2189,9 +2206,18 @@
 VALUE
 rb_mod_remove_cvar(VALUE mod, VALUE name)
 {
-    const ID id = rb_to_id(name);
+    const ID id = rb_check_id(name);
     st_data_t val, n = id;
 
+    if (!id) {
+	if (rb_is_class_name(name)) {
+	    rb_name_error_str(name, "class variable %s not defined for %s",
+			      RSTRING_PTR(name), rb_class2name(mod));
+	}
+	else {
+	    rb_name_error_str(name, "wrong class variable name %s", RSTRING_PTR(name));
+	}
+    }
     if (!rb_is_class_id(id)) {
 	rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
     }
Index: object.c
===================================================================
--- object.c	(revision 32644)
+++ object.c	(revision 32645)
@@ -1833,8 +1833,14 @@
     else {
 	rb_scan_args(argc, argv, "11", &name, &recur);
     }
-    if (!(id = rb_check_id(name)) && rb_is_const_name(name))
-	return Qfalse;
+    if (!(id = rb_check_id(name))) {
+	if (rb_is_const_name(name)) {
+	    return Qfalse;
+	}
+	else {
+	    rb_name_error_str(name, "wrong constant name %s", RSTRING_PTR(name));
+	}
+    }
     if (!rb_is_const_id(id)) {
 	rb_name_error(id, "wrong constant name %s", rb_id2name(id));
     }
@@ -1864,8 +1870,16 @@
 static VALUE
 rb_obj_ivar_get(VALUE obj, VALUE iv)
 {
-    ID id = rb_to_id(iv);
+    ID id = rb_check_id(iv);
 
+    if (!id) {
+	if (rb_is_instance_name(iv)) {
+	    return Qnil;
+	}
+	else {
+	    rb_name_error_str(iv, "`%s' is not allowed as an instance variable name", RSTRING_PTR(iv));
+	}
+    }
     if (!rb_is_instance_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
     }
@@ -1926,7 +1940,14 @@
 {
     ID id = rb_check_id(iv);
 
-    if (!id && rb_is_instance_name(iv)) return Qfalse;
+    if (!id) {
+	if (rb_is_instance_name(iv)) {
+	    return Qfalse;
+	}
+	else {
+	    rb_name_error_str(iv, "`%s' is not allowed as an instance variable name", RSTRING_PTR(iv));
+	}
+    }
     if (!rb_is_instance_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
     }
@@ -1950,8 +1971,17 @@
 static VALUE
 rb_mod_cvar_get(VALUE obj, VALUE iv)
 {
-    ID id = rb_to_id(iv);
+    ID id = rb_check_id(iv);
 
+    if (!id) {
+	if (rb_is_class_name(iv)) {
+	    rb_name_error_str(iv, "uninitialized class variable %s in %s",
+			      RSTRING_PTR(iv), rb_class2name(obj));
+	}
+	else {
+	    rb_name_error_str(iv, "`%s' is not allowed as a class variable name", RSTRING_PTR(iv));
+	}
+    }
     if (!rb_is_class_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
     }
@@ -2006,7 +2036,14 @@
 {
     ID id = rb_check_id(iv);
 
-    if (!id && rb_is_class_name(iv)) return Qfalse;
+    if (!id) {
+	if (rb_is_class_name(iv)) {
+	    return Qfalse;
+	}
+	else {
+	    rb_name_error_str(iv, "`%s' is not allowed as a class variable name", RSTRING_PTR(iv));
+	}
+    }
     if (!rb_is_class_id(id)) {
 	rb_name_error(id, "`%s' is not allowed as a class variable name", rb_id2name(id));
     }
Index: proc.c
===================================================================
--- proc.c	(revision 32644)
+++ proc.c	(revision 32645)
@@ -28,6 +28,7 @@
 
 static VALUE bmcall(VALUE, VALUE);
 static int method_arity(VALUE);
+static ID attached;
 
 /* Proc */
 
@@ -1139,6 +1140,29 @@
     return data->me.klass;
 }
 
+static void
+rb_method_name_error(VALUE klass, VALUE str)
+{
+    const char *s0 = " class";
+    VALUE c = klass;
+
+    if (FL_TEST(c, FL_SINGLETON)) {
+	VALUE obj = rb_ivar_get(klass, attached);
+
+	switch (TYPE(obj)) {
+	  case T_MODULE:
+	  case T_CLASS:
+	    c = obj;
+	    s0 = "";
+	}
+    }
+    else if (RB_TYPE_P(c, T_MODULE)) {
+	s0 = " module";
+    }
+    rb_name_error_str(str, "undefined method `%s' for%s `%s'",
+		      RSTRING_PTR(str), s0, rb_class2name(c));
+}
+
 /*
  *  call-seq:
  *     obj.method(sym)    -> method
@@ -1170,7 +1194,11 @@
 VALUE
 rb_obj_method(VALUE obj, VALUE vid)
 {
-    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, FALSE);
+    ID id = rb_check_id(vid);
+    if (!id) {
+	rb_method_name_error(CLASS_OF(obj), vid);
+    }
+    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, FALSE);
 }
 
 /*
@@ -1183,7 +1211,11 @@
 VALUE
 rb_obj_public_method(VALUE obj, VALUE vid)
 {
-    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, TRUE);
+    ID id = rb_check_id(vid);
+    if (!id) {
+	rb_method_name_error(CLASS_OF(obj), vid);
+    }
+    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, TRUE);
 }
 
 /*
@@ -1220,7 +1252,11 @@
 static VALUE
 rb_mod_instance_method(VALUE mod, VALUE vid)
 {
-    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, FALSE);
+    ID id = rb_check_id(vid);
+    if (!id) {
+	rb_method_name_error(mod, vid);
+    }
+    return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE);
 }
 
 /*
@@ -1233,7 +1269,11 @@
 static VALUE
 rb_mod_public_instance_method(VALUE mod, VALUE vid)
 {
-    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, TRUE);
+    ID id = rb_check_id(vid);
+    if (!id) {
+	rb_method_name_error(mod, vid);
+    }
+    return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE);
 }
 
 /*
@@ -1747,7 +1787,7 @@
     rb_str_buf_cat2(str, ": ");
 
     if (FL_TEST(data->me.klass, FL_SINGLETON)) {
-	VALUE v = rb_iv_get(data->me.klass, "__attached__");
+	VALUE v = rb_ivar_get(data->me.klass, attached);
 
 	if (data->recv == Qundef) {
 	    rb_str_buf_append(str, rb_inspect(data->me.klass));
@@ -2234,5 +2274,6 @@
     rb_define_method(rb_cBinding, "dup", binding_dup, 0);
     rb_define_method(rb_cBinding, "eval", bind_eval, -1);
     rb_define_global_function("binding", rb_f_binding, 0);
+    attached = rb_intern("__attached__");
 }
 
Index: error.c
===================================================================
--- error.c	(revision 32644)
+++ error.c	(revision 32645)
@@ -812,6 +812,21 @@
     rb_exc_raise(exc);
 }
 
+void
+rb_name_error_str(VALUE str, const char *fmt, ...)
+{
+    VALUE exc, argv[2];
+    va_list args;
+
+    va_start(args, fmt);
+    argv[0] = rb_vsprintf(fmt, args);
+    va_end(args);
+
+    argv[1] = str;
+    exc = rb_class_new_instance(2, argv, rb_eNameError);
+    rb_exc_raise(exc);
+}
+
 /*
  * call-seq:
  *   NameError.new(msg [, name])  -> name_error
Index: test/ruby/test_symbol.rb
===================================================================
--- test/ruby/test_symbol.rb	(revision 32644)
+++ test/ruby/test_symbol.rb	(revision 32645)
@@ -172,4 +172,29 @@
       assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
     end
   end
+
+  def test_no_inadvertent_symbol_creation2
+    feature5079 = '[ruby-core:38404]'
+    c = Class.new
+    s = "gadzoooks"
+    {:instance_variable_get => ["@#{s}1", nil],
+     :class_variable_get => ["@@#{s}1", NameError],
+     :remove_instance_variable => ["@#{s}2", NameError],
+     :remove_class_variable => ["@@#{s}2", NameError],
+     :remove_const => ["A#{s}", NameError],
+     :method => ["#{s}1", NameError],
+     :public_method => ["#{s}2", NameError],
+     :instance_method => ["#{s}3", NameError],
+     :public_instance_method => ["#{s}4", NameError],
+    }.each do |meth, arr|
+      str, ret = arr
+      msg = "#{meth}(#{str}) #{feature5079}"
+      if ret.is_a?(Class) && (ret < Exception)
+        assert_raises(ret){c.send(meth, str)}
+      else
+        assert(c.send(meth, str) == ret, msg)
+      end
+      assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
+    end
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]