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

ruby-changes:28049

From: nobu <ko1@a...>
Date: Thu, 4 Apr 2013 16:55:22 +0900 (JST)
Subject: [ruby-changes:28049] nobu:r40101 (trunk): struct.c: avoid inadvertent symbol creation

nobu	2013-04-04 16:55:11 +0900 (Thu, 04 Apr 2013)

  New Revision: 40101

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

  Log:
    struct.c: avoid inadvertent symbol creation
    
    * struct.c (make_struct): avoid inadvertent symbol creation.
      (rb_struct_aref): ditto.
      (rb_struct_aset): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/struct.c
    trunk/test/-ext-/symbol/test_inadvertent_creation.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40100)
+++ ChangeLog	(revision 40101)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Apr  4 16:55:08 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* struct.c (make_struct): avoid inadvertent symbol creation.
+	  (rb_struct_aref): ditto.
+	  (rb_struct_aset): ditto.
+
 Thu Apr  4 16:54:40 2013  Nobuyoshi Nakada  <nobu@r...>
 
 	* object.c (rb_mod_const_set): avoid inadvertent symbol creation.
Index: struct.c
===================================================================
--- struct.c	(revision 40100)
+++ struct.c	(revision 40101)
@@ -187,10 +187,11 @@ make_struct(VALUE name, VALUE members, V https://github.com/ruby/ruby/blob/trunk/struct.c#L187
     else {
 	/* old style: should we warn? */
 	name = rb_str_to_str(name);
-	id = rb_to_id(name);
-	if (!rb_is_const_id(id)) {
-	    rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name));
+	if (!rb_is_const_name(name)) {
+	    rb_name_error_str(name, "identifier %"PRIsVALUE" needs to be constant",
+			      QUOTE(name));
 	}
+	id = rb_to_id(name);
 	if (rb_const_defined_at(klass, id)) {
 	    rb_warn("redefining constant Struct::%s", StringValuePtr(name));
 	    rb_mod_remove_const(klass, ID2SYM(id));
@@ -672,8 +673,16 @@ rb_struct_aref(VALUE s, VALUE idx) https://github.com/ruby/ruby/blob/trunk/struct.c#L673
 {
     long i;
 
-    if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) {
-	return rb_struct_aref_id(s, rb_to_id(idx));
+    if (RB_TYPE_P(idx, T_SYMBOL)) {
+	return rb_struct_aref_id(s, SYM2ID(idx));
+    }
+    else if (RB_TYPE_P(idx, T_STRING)) {
+	ID id = rb_check_id(&idx);
+	if (!id) {
+	    rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
+			      QUOTE(idx));
+	}
+	return rb_struct_aref_id(s, id);
     }
 
     i = NUM2LONG(idx);
@@ -739,8 +748,16 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE https://github.com/ruby/ruby/blob/trunk/struct.c#L748
 {
     long i;
 
-    if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) {
-	return rb_struct_aset_id(s, rb_to_id(idx), val);
+    if (RB_TYPE_P(idx, T_SYMBOL)) {
+	return rb_struct_aset_id(s, SYM2ID(idx), val);
+    }
+    if (RB_TYPE_P(idx, T_STRING)) {
+	ID id = rb_check_id(&idx);
+	if (!id) {
+	    rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
+			      QUOTE(idx));
+	}
+	return rb_struct_aset_id(s, id, val);
     }
 
     i = NUM2LONG(idx);
Index: test/-ext-/symbol/test_inadvertent_creation.rb
===================================================================
--- test/-ext-/symbol/test_inadvertent_creation.rb	(revision 40100)
+++ test/-ext-/symbol/test_inadvertent_creation.rb	(revision 40101)
@@ -214,5 +214,25 @@ module Test_Symbol https://github.com/ruby/ruby/blob/trunk/test/-ext-/symbol/test_inadvertent_creation.rb#L214
       assert_raise(NameError) {obj.instance_variable_set(name, true)}
       assert_not_send([Bug::Symbol, :interned?, name])
     end
+
+    def test_struct_new
+      name = noninterned_name
+      assert_raise(NameError) {Struct.new(name)}
+      assert_not_send([Bug::Symbol, :interned?, name])
+    end
+
+    def test_struct_aref
+      s = Struct.new(:foo).new
+      name = noninterned_name
+      assert_raise(NameError) {s[name]}
+      assert_not_send([Bug::Symbol, :interned?, name])
+    end
+
+    def test_struct_aset
+      s = Struct.new(:foo).new
+      name = noninterned_name
+      assert_raise(NameError) {s[name] = true}
+      assert_not_send([Bug::Symbol, :interned?, name])
+    end
   end
 end

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

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