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

ruby-changes:30909

From: nobu <ko1@a...>
Date: Fri, 20 Sep 2013 15:02:09 +0900 (JST)
Subject: [ruby-changes:30909] nobu:r42988 (trunk): parse.y: junk sigil only names

nobu	2013-09-20 15:01:57 +0900 (Fri, 20 Sep 2013)

  New Revision: 42988

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

  Log:
    parse.y: junk sigil only names
    
    * parse.y (intern_str): sigil only names are junk, at least one
      identifier character is needed.  [ruby-dev:47723] [Bug #8928]
    * parse.y (rb_enc_symname_type): fix out of bound access.

  Added files:
    trunk/ext/-test-/symbol/type.c
    trunk/test/-ext-/symbol/test_type.rb
  Modified files:
    trunk/ChangeLog
    trunk/parse.y
    trunk/test/ruby/test_module.rb
    trunk/test/ruby/test_object.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42987)
+++ ChangeLog	(revision 42988)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Sep 20 15:01:46 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (intern_str): sigil only names are junk, at least one
+	  identifier character is needed.  [ruby-dev:47723] [Bug #8928]
+
+	* parse.y (rb_enc_symname_type): fix out of bound access.
+
 Fri Sep 20 14:14:32 2013  Tanaka Akira  <akr@f...>
 
 	* ext/-test-/printf/printf.c (printf_test_call): Fix an end of buffer
Index: parse.y
===================================================================
--- parse.y	(revision 42987)
+++ parse.y	(revision 42988)
@@ -10367,6 +10367,7 @@ rb_enc_symname_type(const char *name, lo https://github.com/ruby/ruby/blob/trunk/parse.y#L10367
 	if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
 	    return -1;
 	while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
+	if (m >= e) break;
 	switch (*m) {
 	  case '!': case '?':
 	    if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
@@ -10484,7 +10485,8 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/parse.y#L10485
     enc = rb_enc_get(str);
     symenc = enc;
 
-    if (rb_cString && !rb_enc_asciicompat(enc)) {
+    if (!len || (rb_cString && !rb_enc_asciicompat(enc))) {
+      junk:
 	id = ID_JUNK;
 	goto new_id;
     }
@@ -10492,6 +10494,7 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/parse.y#L10494
     id = 0;
     switch (*m) {
       case '$':
+	if (len < 2) goto junk;
 	id |= ID_GLOBAL;
 	if ((mb = is_special_global_name(++m, e, enc)) != 0) {
 	    if (!--mb) symenc = rb_usascii_encoding();
@@ -10500,10 +10503,12 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/parse.y#L10503
 	break;
       case '@':
 	if (m[1] == '@') {
+	    if (len < 3) goto junk;
 	    m++;
 	    id |= ID_CLASS;
 	}
 	else {
+	    if (len < 2) goto junk;
 	    id |= ID_INSTANCE;
 	}
 	m++;
@@ -10530,6 +10535,8 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/parse.y#L10535
     }
     if (name[last] == '=') {
 	/* attribute assignment */
+	if (!rb_enc_symname2_p(name, last, enc))
+	    goto junk;
 	id = rb_intern3(name, last, enc);
 	if (id > tLAST_OP_ID && !is_attrset_id(id)) {
 	    enc = rb_enc_get(rb_id2str(id));
Index: ext/-test-/symbol/type.c
===================================================================
--- ext/-test-/symbol/type.c	(revision 0)
+++ ext/-test-/symbol/type.c	(revision 42988)
@@ -0,0 +1,34 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/symbol/type.c#L1
+#include "ruby.h"
+
+#ifdef HAVE_RB_IS_CONST_NAME
+# define get_symbol_type(type, t, name) do { \
+	ID id = rb_check_id(&name); \
+	t = (id ? rb_is_##type##_id(id) : rb_is_##type##_name(name)); \
+    } while (0)
+#else
+# define get_symbol_type(type, t, name) do { \
+	t = rb_is_##type##_id(rb_to_id(name)); \
+    } while (0)
+#endif
+
+#define define_symbol_type_p(type) \
+static VALUE \
+bug_sym_##type##_p(VALUE self, VALUE name) \
+{ \
+    int t; \
+    get_symbol_type(type, t, name); \
+    return (t ? Qtrue : Qfalse); \
+}
+
+#define declare_symbol_type_p(type) \
+    rb_define_singleton_method(klass, #type"?", bug_sym_##type##_p, 1);
+
+#define FOREACH_ID_TYPES(x) x(const) x(class) x(global) x(instance) x(attrset) x(local) x(junk)
+
+FOREACH_ID_TYPES(define_symbol_type_p)
+
+void
+Init_type(VALUE klass)
+{
+    FOREACH_ID_TYPES(declare_symbol_type_p)
+}

Property changes on: ext/-test-/symbol/type.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 42987)
+++ test/ruby/test_module.rb	(revision 42988)
@@ -688,6 +688,7 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L688
     c.class_eval('@@foo = :foo')
     assert_equal(:foo, c.class_variable_get(:@@foo))
     assert_raise(NameError) { c.class_variable_get(:@@bar) } # c.f. instance_variable_get
+    assert_raise(NameError) { c.class_variable_get(:'@@') }
     assert_raise(NameError) { c.class_variable_get('@@') }
     assert_raise(NameError) { c.class_variable_get(:foo) }
     assert_raise(NameError) { c.class_variable_get("bar") }
@@ -704,6 +705,7 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L705
     c = Class.new
     c.class_variable_set(:@@foo, :foo)
     assert_equal(:foo, c.class_eval('@@foo'))
+    assert_raise(NameError) { c.class_variable_set(:'@@', 1) }
     assert_raise(NameError) { c.class_variable_set('@@', 1) }
     assert_raise(NameError) { c.class_variable_set(:foo, 1) }
     assert_raise(NameError) { c.class_variable_set("bar", 1) }
@@ -722,6 +724,8 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L724
     c.class_eval('@@foo = :foo')
     assert_equal(true, c.class_variable_defined?(:@@foo))
     assert_equal(false, c.class_variable_defined?(:@@bar))
+    assert_raise(NameError) { c.class_variable_defined?(:'@@') }
+    assert_raise(NameError) { c.class_variable_defined?('@@') }
     assert_raise(NameError) { c.class_variable_defined?(:foo) }
     assert_raise(NameError) { c.class_variable_defined?("bar") }
     assert_raise(TypeError) { c.class_variable_defined?(1) }
Index: test/ruby/test_object.rb
===================================================================
--- test/ruby/test_object.rb	(revision 42987)
+++ test/ruby/test_object.rb	(revision 42988)
@@ -163,6 +163,8 @@ class TestObject < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_object.rb#L163
     o.instance_eval { @foo = :foo }
     assert_equal(:foo, o.instance_variable_get(:@foo))
     assert_equal(nil, o.instance_variable_get(:@bar))
+    assert_raise(NameError) { o.instance_variable_get('@') }
+    assert_raise(NameError) { o.instance_variable_get(:'@') }
     assert_raise(NameError) { o.instance_variable_get(:foo) }
     assert_raise(NameError) { o.instance_variable_get("bar") }
     assert_raise(TypeError) { o.instance_variable_get(1) }
@@ -178,6 +180,8 @@ class TestObject < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_object.rb#L180
     o = Object.new
     o.instance_variable_set(:@foo, :foo)
     assert_equal(:foo, o.instance_eval { @foo })
+    assert_raise(NameError) { o.instance_variable_set(:'@', 1) }
+    assert_raise(NameError) { o.instance_variable_set('@', 1) }
     assert_raise(NameError) { o.instance_variable_set(:foo, 1) }
     assert_raise(NameError) { o.instance_variable_set("bar", 1) }
     assert_raise(TypeError) { o.instance_variable_set(1, 1) }
@@ -195,6 +199,8 @@ class TestObject < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_object.rb#L199
     o.instance_eval { @foo = :foo }
     assert_equal(true, o.instance_variable_defined?(:@foo))
     assert_equal(false, o.instance_variable_defined?(:@bar))
+    assert_raise(NameError) { o.instance_variable_defined?(:'@') }
+    assert_raise(NameError) { o.instance_variable_defined?('@') }
     assert_raise(NameError) { o.instance_variable_defined?(:foo) }
     assert_raise(NameError) { o.instance_variable_defined?("bar") }
     assert_raise(TypeError) { o.instance_variable_defined?(1) }
Index: test/-ext-/symbol/test_type.rb
===================================================================
--- test/-ext-/symbol/test_type.rb	(revision 0)
+++ test/-ext-/symbol/test_type.rb	(revision 42988)
@@ -0,0 +1,96 @@ https://github.com/ruby/ruby/blob/trunk/test/-ext-/symbol/test_type.rb#L1
+require 'test/unit'
+require "-test-/symbol"
+
+module Test_Symbol
+  class TestType < Test::Unit::TestCase
+    def assert_symtype(sym, pred, msg = nil)
+      assert_send([Bug::Symbol, pred, sym], msg)
+    end
+
+    def assert_not_symtype(sym, pred, msg = nil)
+      assert_not_send([Bug::Symbol, pred, sym], msg)
+    end
+
+    def test_const
+      assert_symtype("Foo", :const?)
+      assert_not_symtype("F!", :const?)
+      assert_not_symtype("foo", :const?)
+      assert_not_symtype("@foo", :const?)
+      assert_not_symtype("@@foo", :const?)
+      assert_not_symtype("$foo", :const?)
+      assert_not_symtype("foo=", :const?)
+      assert_not_symtype("[foo]", :const?)
+      assert_not_symtype("xFoo", :const?)
+    end
+
+    def test_local
+      assert_symtype("foo", :local?)
+      assert_symtype("fooBar", :local?)
+      assert_symtype("foo_bar", :local?)
+      assert_not_symtype("foo!", :local?)
+      assert_not_symtype("foo?", :local?)
+      assert_not_symtype("Foo", :local?)
+      assert_not_symtype("@foo", :local?)
+      assert_not_symtype("@@foo", :local?)
+      assert_not_symtype("$foo", :local?)
+      assert_not_symtype("foo=", :local?)
+      assert_not_symtype("[foo]", :local?)
+    end
+
+    def test_global
+      assert_symtype("$foo", :global?)
+      assert_symtype("$$", :global?)
+      assert_not_symtype("$()", :global?)
+      assert_not_symtype("$", :global?)
+      assert_not_symtype("foo", :global?)
+      assert_not_symtype("Foo", :global?)
+      assert_not_symtype("@foo", :global?)
+      assert_not_symtype("@@foo", :global?)
+      assert_not_symtype("foo=", :global?)
+      assert_not_symtype("[foo]", :global?)
+    end
+
+    def test_instance
+      assert_symtype("@foo", :instance?)
+      assert_not_symtype("@", :instance?)
+      assert_not_symtype("@1", :instance?)
+      assert_not_symtype("@@", :instance?)
+      assert_not_symtype("foo", :instance?)
+      assert_not_symtype("Foo", :instance?)
+      assert_not_symtype("@@foo", :instance?)
+      assert_not_symtype("$foo", :instance?)
+      assert_not_symtype("foo=", :instance?)
+      assert_not_symtype("[foo]", :instance?)
+    end
+
+    def test_class
+      assert_symtype("@@foo", :class?)
+      assert_not_symtype("@@", :class?)
+      assert_not_symtype("@", :class?)
+      assert_not_symtype("@@1", :class?)
+      assert_not_symtype("foo", :class?)
+      assert_not_symtype("Foo", :class?)
+      assert_not_symtype("@foo", :class?)
+      assert_not_symtype("$foo", :class?)
+      assert_not_symtype("foo=", :class?)
+      assert_not_symtype("[foo]", :class?)
+    end
+
+    def test_attrset
+      assert_symtype("foo=", :attrset?)
+      assert_symtype("Foo=", :attrset?)
+      assert_symtype("@foo=", :attrset?)
+      assert_symtype("@@foo=", :attrset?)
+      assert_symtype("$foo=", :attrset?)
+      assert_not_symtype("0=", :attrset?)
+      assert_not_symtype("@=", :attrset?)
+      assert_not_symtype("@@=", :attrset?)
+      assert_not_symtype("foo", :attrset?)
+      assert_not_symtype("Foo", :attrset?)
+      assert_not_symtype("@foo", :attrset?)
+      assert_not_symtype("@@foo", :attrset?)
+      assert_not_symtype("$foo", :attrset?)
+      assert_not_symtype("[foo]", :attrset?)
+    end
+  end
+end

Property changes on: test/-ext-/symbol/test_type.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


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

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