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

ruby-changes:15528

From: nobu <ko1@a...>
Date: Wed, 21 Apr 2010 13:45:28 +0900 (JST)
Subject: [ruby-changes:15528] Ruby:r27431 (trunk): * parse.y (regexp): check each fragments.

nobu	2010-04-21 13:44:58 +0900 (Wed, 21 Apr 2010)

  New Revision: 27431

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

  Log:
    * parse.y (regexp): check each fragments.   [ruby-core:27374]

  Modified files:
    trunk/ChangeLog
    trunk/parse.y
    trunk/test/ruby/test_regexp.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 27430)
+++ ChangeLog	(revision 27431)
@@ -1,3 +1,7 @@
+Wed Apr 21 13:44:54 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (regexp): check each fragments.   [ruby-core:27374]
+
 Wed Apr 21 13:36:01 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* parse.y (parser_yylex): reverted r27388 due to backward
Index: parse.y
===================================================================
--- parse.y	(revision 27430)
+++ parse.y	(revision 27431)
@@ -362,6 +362,7 @@
 #define arg_concat(h,t) arg_concat_gen(parser,h,t)
 static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*);
 #define literal_concat(h,t) literal_concat_gen(parser,h,t)
+static int literal_concat0(struct parser_params *, VALUE, VALUE);
 static NODE *new_evstr_gen(struct parser_params*,NODE*);
 #define new_evstr(n) new_evstr_gen(parser,n)
 static NODE *evstr2dstr_gen(struct parser_params*,NODE*);
@@ -415,7 +416,7 @@
 #define reg_compile(str,options) reg_compile_gen(parser, str, options)
 static void reg_fragment_setenc_gen(struct parser_params*, VALUE, int);
 #define reg_fragment_setenc(str,options) reg_fragment_setenc_gen(parser, str, options)
-static void reg_fragment_check_gen(struct parser_params*, VALUE, int);
+static int reg_fragment_check_gen(struct parser_params*, VALUE, int);
 #define reg_fragment_check(str,options) reg_fragment_check_gen(parser, str, options)
 static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
 #define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,regexp,match)
@@ -684,7 +685,7 @@
 %token <num>  tREGEXP_END
 
 %type <node> singleton strings string string1 xstring regexp
-%type <node> string_contents xstring_contents string_content
+%type <node> string_contents xstring_contents regexp_contents string_content
 %type <node> words qwords word_list qword_list word
 %type <node> literal numeric dsym cpath
 %type <node> top_compstmt top_stmts top_stmt
@@ -3852,12 +3853,12 @@
 		    }
 		;
 
-regexp		: tREGEXP_BEG xstring_contents tREGEXP_END
+regexp		: tREGEXP_BEG regexp_contents tREGEXP_END
 		    {
 		    /*%%%*/
 			int options = $3;
 			NODE *node = $2;
-                        NODE *list;
+			NODE *list, *prev;
 			if (!node) {
 			    node = NEW_LIT(reg_compile(STR_NEW0(), options));
 			}
@@ -3880,11 +3881,33 @@
 			    }
 			    node->nd_cflag = options & RE_OPTION_MASK;
 			    if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options);
-                            for (list = node->nd_next; list; list = list->nd_next) {
-                                if (nd_type(list->nd_head) == NODE_STR) {
-                                    reg_fragment_check(list->nd_head->nd_lit, options);
+			    for (list = (prev = node)->nd_next; list; list = list->nd_next) {
+				if (nd_type(list->nd_head) == NODE_STR) {
+				    VALUE tail = list->nd_head->nd_lit;
+				    if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) {
+					if (!literal_concat0(parser, prev->nd_lit, tail)) {
+					    node = 0;
+					    break;
+					}
+					rb_str_resize(tail, 0);
+					prev->nd_next = list->nd_next;
+					rb_gc_force_recycle((VALUE)list->nd_head);
+					rb_gc_force_recycle((VALUE)list);
+					list = prev;
+				    }
+				    else {
+					prev = list;
+				    }
                                 }
+				else {
+				    prev = 0;
+				}
                             }
+			    if (!node->nd_next) {
+				VALUE src = node->nd_lit;
+				nd_set_type(node, NODE_LIT);
+				node->nd_lit = reg_compile(src, options);
+			    }
 			    break;
 			}
 			$$ = node;
@@ -4012,6 +4035,43 @@
 		    }
 		;
 
+regexp_contents: /* none */
+		    {
+		    /*%%%*/
+			$$ = 0;
+		    /*%
+			$$ = dispatch0(regexp_new);
+		    %*/
+		    }
+		| regexp_contents string_content
+		    {
+		    /*%%%*/
+			NODE *head = $1, *tail = $2;
+			if (!head) {
+			    $$ = tail;
+			}
+			else if (!tail) {
+			    $$ = head;
+			}
+			else {
+			    switch (nd_type(head)) {
+			      case NODE_STR:
+				nd_set_type(head, NODE_DSTR);
+				break;
+			      case NODE_DSTR:
+				break;
+			      default:
+				head = list_append(NEW_DSTR(Qnil), head);
+				break;
+			    }
+			    $$ = list_append(head, tail);
+			}
+		    /*%
+			$$ = dispatch2(regexp_add, $1, $2);
+		    %*/
+		    }
+		;
+
 string_content	: tSTRING_CONTENT
 		| tSTRING_DVAR
 		    {
@@ -9064,7 +9124,7 @@
         c, rb_enc_name(rb_enc_get(str)));
 }
 
-static void
+static int
 reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
 {
     VALUE err;
@@ -9074,7 +9134,9 @@
         err = rb_obj_as_string(err);
         compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
 	RB_GC_GUARD(err);
+	return 0;
     }
+    return 1;
 }
 
 typedef struct {
Index: test/ruby/test_regexp.rb
===================================================================
--- test/ruby/test_regexp.rb	(revision 27430)
+++ test/ruby/test_regexp.rb	(revision 27431)
@@ -477,7 +477,7 @@
     end.value
     assert(m.tainted?)
     assert_nothing_raised('[ruby-core:26137]') {
-      m = proc {$SAFE = 4; %r"#{}"o}.call
+      m = proc {$SAFE = 4; %r"#{ }"o}.call
     }
     assert(m.tainted?)
   end
@@ -807,4 +807,9 @@
     assert_equal("1", $1)
     assert_equal(" " * 4999999, $2)
   end
+
+  def test_invalid_fragment
+    bug2547 = '[ruby-core:27374]'
+    assert_raise(SyntaxError, bug2547) {eval('/#{"\\\\"}y/')}
+  end
 end

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

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