まつもと ゆきひろです

In message "[ruby-list:10481] Enumerable#collect bug?"
    on 98/10/30, Kazuhiro HIWADA <hiwada / kuee.kyoto-u.ac.jp> writes:

|ひわだです。
|
|以下の script で collect がちょっと予想外の動作をします。
|1.1c0, 1.1c6 を使っています。

ええと,予想された答えでしょうがバグです.^^;;;

で,これはブロック引数の受渡しのバグでした.
今試した範囲内では大丈夫そうだったのですが,以下のパッチを試
してみて下さい.

なんか他の修正も混じってますが,便利なものばかりなので一緒に
しておきます.というか,これらが1.1c7の変更の本質的な部分の
ような気がする.

--- eval.c	1998/09/08 09:17:32	1.1.1.2.2.80
+++ eval.c	1998/10/30 05:42:26
@@ -424,8 +424,2 @@
 
-#define PUSH_BLOCK2(b) {		\
-    struct BLOCK _block;		\
-    _block = *b;			\
-    _block.prev = the_block;		\
-    the_block = &_block;
-
 #define POP_BLOCK() 			\
@@ -532,3 +526,3 @@
     else {
-	dyna_var_push(id, value);
+	dyna_var_asgn(id, value);
     }
@@ -706,6 +700,2 @@
 	}
-	if (verbose) {
-	    Warning("Insecure operation - %s",
-		    rb_id2name(the_frame->last_func));
-	}
     }
@@ -1614,2 +1604,6 @@
       case NODE_BLOCK:
+	if (!node->nd_next) {
+	    node = node->nd_head;
+	    goto again;
+	}
 	while (node) {
@@ -2339,2 +2333,3 @@
 		    str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+		    if (str_tainted(str2)) str_taint(str);
 		}
@@ -3355,3 +3350,3 @@
 
-    if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX)
+    if ((++tick & 0x3ff) == 0 && stack_length() > STACK_LEVEL_MAX)
 	Raise(eSysStackError, "stack level too deep");
@@ -5016,2 +5011,3 @@
 {
+    struct BLOCK * volatile old_block;
     struct BLOCK *data;
@@ -5037,3 +5033,4 @@
     /* PUSH BLOCK from data */
-    PUSH_BLOCK2(data);
+    old_block = the_block;
+    the_block = data;
     PUSH_ITER(ITER_CUR);
@@ -5075,3 +5072,3 @@
     }
-    POP_BLOCK();
+    the_block = old_block;
     safe_level = safe;
@@ -5103,2 +5100,3 @@
     VALUE block = rb_eval(self, node->nd_body);
+    struct BLOCK * volatile old_block;
     struct BLOCK *data;
@@ -5124,3 +5122,4 @@
     /* PUSH BLOCK from data */
-    PUSH_BLOCK2(data);
+    old_block = the_block;
+    the_block = data;
     PUSH_ITER(ITER_PRE);
@@ -5153,3 +5152,3 @@
     }
-    POP_BLOCK();
+    the_block = old_block;
     safe_level = safe;