[ruby-dev:31862] Re: huge `if' dumps core

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-09-25 19:16:16 UTC
List: ruby-dev #31862
なかだです。

At Tue, 25 Sep 2007 21:12:42 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:31855]:
> |> 以下のようにすると 1.8 、1.9 共に落ちます。
> 
> |> ALLOCA_N が原因のようです。
> |
> |さすがに、1MBを越えるエラーメッセージが出てくれてもあまりうれし
> |くないのでは。
> 
> でしょうね。なかださんのパッチをコミットしてくださいませんか?

1.8のほうはどうしましょうか。rb_enc_prev_char()相当がないので、
re_adjust_startpos()から流用するなら以下のような感じです。

というか、手元では[ruby-talk:247595]が当たったままだったので、そ
もそも"memory exhausted"自体が発生しなかったのですが。


Index: parse.y
===================================================================
--- parse.y	(revision 13508)
+++ parse.y	(working copy)
@@ -2517,5 +2517,7 @@ yyerror(msg)
     const char *msg;
 {
-    char *p, *pe, *buf;
+    const int max_line_margin = 30;
+    const char *p, *pe;
+    char *buf;
     int len, i;
 
@@ -2536,15 +2538,30 @@ yyerror(msg)
     len = pe - p;
     if (len > 4) {
+	char *p2;
+	const char *pre = "", *post = "";
+
+	if (len > max_line_margin * 2 + 10) {
+	    int re_mbc_startpos _((const char *, int, int, int));
+	    if ((len = lex_p - p) > max_line_margin) {
+		p = p + re_mbc_startpos(p, len, len - max_line_margin, 0);
+		pre = "...";
+	    }
+	    if ((len = pe - lex_p) > max_line_margin) {
+		pe = lex_p + re_mbc_startpos(lex_p, len, max_line_margin, 1);
+		post = "...";
+	    }
+	    len = pe - p;
+	}
 	buf = ALLOCA_N(char, len+2);
 	MEMCPY(buf, p, char, len);
 	buf[len] = '\0';
-	rb_compile_error_append("%s", buf);
+	rb_compile_error_append("%s%s%s", pre, buf, post);
 
 	i = lex_p - p;
-	p = buf; pe = p + len;
+	p2 = buf; pe = buf + len;
 
-	while (p < pe) {
-	    if (*p != '\t') *p = ' ';
-	    p++;
+	while (p2 < pe) {
+	    if (*p2 != '\t') *p2 = ' ';
+	    p2++;
 	}
 	buf[i] = '^';
Index: regex.c
===================================================================
--- regex.c	(revision 13508)
+++ regex.c	(working copy)
@@ -3110,4 +3110,26 @@ re_compile_fastmap(bufp)
 /* adjust startpos value to the position between characters. */
 int
+re_mbc_startpos(string, size, startpos, range)
+     const char *string;
+     int size, startpos, range;
+{
+  int i = mbc_startpos(string, startpos);
+
+  if (i < startpos) {
+    if (range > 0) {
+      startpos = i + mbclen(string[i]);
+    }
+    else {
+      int len = mbclen(string[i]);
+      if (i + len <= startpos)
+	startpos = i + len;
+      else
+	startpos = i;
+    }
+  }
+  return startpos;
+}
+
+int
 re_adjust_startpos(bufp, string, size, startpos, range)
      struct re_pattern_buffer *bufp;
@@ -3122,18 +3144,5 @@ re_adjust_startpos(bufp, string, size, s
   /* Adjust startpos for mbc string */
   if (current_mbctype && startpos>0 && !(bufp->options&RE_OPTIMIZE_BMATCH)) {
-    int i = mbc_startpos(string, startpos);
-
-    if (i < startpos) {
-      if (range > 0) {
-	startpos = i + mbclen(string[i]);
-      }
-      else {
-	int len = mbclen(string[i]);
-	if (i + len <= startpos)
-	  startpos = i + len;
-	else
-	  startpos = i;
-      }
-    }
+    startpos = re_mbc_startpos(string, size, startpos, range);
   }
   return startpos;


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread