[Bug:1.9] Enumerator.new { }.take(1).inject(&:+) causes stack overflow

e$B1sF#$G$9!#e(B

e$B0J2<$N$h$&$K$9$k$H!"Ff$Ne(B SystemStackError e$B$,=P$F$-$^$9!#e(B

$ ./ruby -ve ‘Enumerator.new { }.take(1).inject(&:+)’
ruby 1.9.2dev (2009-05-19 trunk 23489) [i686-linux]
-e:1:in proc': stack level too deep (SystemStackError) from -e:1:into_proc’
from -e:1:in `’

1.9.1-p0 e$B$G$bF1$8$G$7$?!#e(B

e$BD4$Y$F$$?$H$3$m!"8=:$N%V%m%C%/$Ne(B cfp->lfp[0]
e$B$,;X$9%V%m%C%/$,e(B
e$B<+J,<+?H$K$J$C$F$$$k$h$&$G$9e(B (e$B@53N$K$O!“B>$N%V%m%C%/$r2r$7$Fe(B
e$B4V@\E*$K=[4D$7$F$$$k$h$&$G$7$?e(B) e$B!#e(B
e$B$=$N$;$$$G!“e(Bvm.c e$B$Ne(B rb_vm_make_proc e$B$He(B
vm_make_proc_from_block e$B$,e(B
e$BAj8_$K8F$S=P$7$”$C$FL58B:F5”$7$F$$$k$h$&$G$9!#e(B

cfp->lfp[0] e$B$,$*$+$7$/$J$k860x$O$?$V$se(B enumerator.c e$B$G!"e(B

  • yielder_new e$B$,e(B rb_iterate(yielder_new_i, …) e$B$r8F$Ve(B
  • passed_block e$B$,@_Dj$5$l$ke(B
  • yielder_new_i e$B$Oe(B Ruby e$B%l%Y%k$N%a%=%C%I$r8F$P$:$K=*N;$9$ke(B
  • passed_block e$B$,@_Dj$5$l$?$^$^!"e(Byielder_new e$B$,=*$o$j!"e(BYARV
    e$B$Ne(B
    eval e$B%k!<%W$KLa$ke(B
  • passed_block e$B$,$I$3$+JQ$J$H$3$m$Ge(B cfp->lfp[0] e$B$KBeF~$5$l$ke(B

e$B$H$$$&N.$l$K$J$C$F$$$k$h$&$K46$8$^$7$?e(B (yielder
e$B$,$I$s$J$b$N$+$Oe(B
e$B$h$/$o$+$C$F$$$^$;$se(B) e$B!#e(B

e$B$=$3$G!"0J2<$N$h$&$K!"e(Byielder_new_i e$B$Ge(B proc
e$B%a%=%C%I$r8F$V$3$H$Ge(B
e$B%P%0$OD>$j$^$7$?!#e(B

Index: enumerator.c

— enumerator.c (revision 23508)
+++ enumerator.c (working copy)
@@ -720,7 +720,7 @@
static VALUE
yielder_new_i(VALUE dummy)
{

  • return yielder_init(yielder_allocate(rb_cYielder),
    rb_block_proc());
  • return yielder_init(yielder_allocate(rb_cYielder),
    rb_funcall(Qnil, rb_intern(“proc”), 0));
    }

static VALUE

e$B$5$5$@$5$s$,$$$$$H8@$C$F$/$l$?$ie(B (e$B$b$7$/$O2?$b8@$o$J$$$J$ie(B)
e$B%3%_%C%H$7$h$&$H;W$$$^$9!#e(B

e$B>e$K4X78$7$F!“e(BRuby
e$B$N%=!<%9%3!<%I$K$O0J2<$N%”%5!<%7%g%s$,0EL[$Ke(B
e$BB8:_$9$k$H;W$C$?$N$G$9$,!"@5$7$$$G$7$g$&$+!#e(B

  • passed_block e$B$,@_Dj$5$l$?$i!"e(Beval e$B%k!<%W$KLa$kA0$Ke(B Ruby
    e$B%l%Y%k$Ne(B
    e$B%a%=%C%I$r8F$s$Ge(B passed_block e$B$r2s<}$5$;$J$$$H$$$1$J$$e(B

  • rb_iterate e$B$de(B rb_block_call
    e$B$NBh0l0z?t$KEO$5$l$k4X?t$O!"$=$NCf$Ge(B
    Ruby e$B%l%Y%k$N%a%=%C%I$r8F$P$J$$$H$$$1$J$$e(B

e$B8e<T$Oe(B C API e$B$K4X$o$kOC$J$N$G!"@5$7$$$h$&$J$ie(B README.EXT
e$B$K=q$-e(B
e$B2C$($?J}$,$$$$$H;W$$$^$9!#$H$$$&$+=q$-2C$($h$&$H;W$$$^$9!#e(B

e$B!!$5$5$@$G$9!%e(B

Yusuke ENDOH wrote::

e$B$=$3$G!"0J2<$N$h$&$K!"e(Byielder_new_i e$B$Ge(B proc e$B%a%=%C%I$r8F$V$3$H$Ge(B
e$B%P%0$OD>$j$^$7$?!#e(B

e$B!!;w$?$h$&$JOC$J$s$G$9$,!$$=$b$=$be(B rb_iterate
e$B$r;H$&>lLL$8$c$J$5$=$&$J!%e(B

Index: enumerator.c

— enumerator.c (e$B%j%S%8%g%se(B 23496)
+++ enumerator.c (e$B:n6H%3%T!<e(B)
@@ -718,12 +718,6 @@
}

static VALUE
-yielder_new_i(VALUE dummy)
-{

  • return yielder_init(yielder_allocate(rb_cYielder),
    rb_block_proc());
    -}

-static VALUE
yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv)
{
return rb_yield_values2(argc, argv);
@@ -732,7 +726,7 @@
static VALUE
yielder_new(void)
{

  • return rb_iterate(yielder_new_i, (VALUE)0, yielder_yield_i,
    (VALUE)0);
  • return yielder_init(yielder_allocate(rb_cYielder),
    rb_proc_new(yielder_yield_i, 0));
    }

/*

e$B>e$K4X78$7$F!“e(BRuby e$B$N%=!<%9%3!<%I$K$O0J2<$N%”%5!<%7%g%s$,0EL[$Ke(B
e$BB8:_$9$k$H;W$C$?$N$G$9$,!"@5$7$$$G$7$g$&$+!#e(B

  • passed_block e$B$,@_Dj$5$l$?$i!"e(Beval e$B%k!<%W$KLa$kA0$Ke(B Ruby e$B%l%Y%k$Ne(B
    e$B%a%=%C%I$r8F$s$Ge(B passed_block e$B$r2s<}$5$;$J$$$H$$$1$J$$e(B

yes.

  • rb_iterate e$B$de(B rb_block_call e$B$NBh0l0z?t$KEO$5$l$k4X?t$O!"$=$NCf$Ge(B
    Ruby e$B%l%Y%k$N%a%=%C%I$r8F$P$J$$$H$$$1$J$$e(B

yes.

e$B8e<T$Oe(B C API e$B$K4X$o$kOC$J$N$G!"@5$7$$$h$&$J$ie(B README.EXT e$B$K=q$-e(B
e$B2C$($?J}$,$$$$$H;W$$$^$9!#$H$$$&$+=q$-2C$($h$&$H;W$$$^$9!#e(B

e$B!!$3$l$O!$<B$Oe(B 1.8 e$B0JA0$H$NHs8_49$NLdBj$@$C$?$s$G$9$h$M!%e(B

e$B!!$3$l$r??LLL$K2r7h$7$h$&$H$9$k$H!$$3$N$h$&$J%l%"%1!<%9$N$?$a$K%V%m%C%/e(B
e$B$r%A%’%C%/$9$kA4$F$N%3!<%I$Ke(B passed_block
e$B$r%A%’%C%/$9$k$h$&$KJQ99$9$kI,e(B
e$BMW$,=P$F$-$F!$$A$g$C$H8=<BE*$8$c$J$$$N$G$9!%e(B

e$B!v%U%l!<%`$r$=$N;~$@$1$$$8$C$A$c$&!$$H$$$&2sHr<jCJ$,$"$k$h$&$J!$e(B
e$B!!7y$J$H$3$m$KGH5Z$7$=$&$J!%e(B

e$B!!Nc$($P!$e(Brb_iterate e$B$Oe(B obsolete
e$B$K$7$F$7$^$C$F!J@)8BIU$-$GB8:_!K!$e(B
rb_block_call
e$B$r;H$&$h$&$K$7$F2<$5$$!$$H%I%-%e%a%s%H$9$k$N$O$I$s$J$b$s$Ge(B
e$B$7$g$&$+!%e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:38521] Re: [Bug:1.9] Enumerator.new {
}.take(1).inject(&:+) causes stack overflow”
on Fri, 22 May 2009 05:39:46 +0900, SASADA Koichi [email protected]
writes:

|e$B!!$3$l$O!$<B$Oe(B 1.8 e$B0JA0$H$NHs8_49$NLdBj$@$C$?$s$G$9$h$M!%e(B
|
|e$B!!$3$l$r??LLL$K2r7h$7$h$&$H$9$k$H!$$3$N$h$&$J%l%“%1!<%9$N$?$a$K%V%m%C%/e(B
|e$B$r%A%‘%C%/$9$kA4$F$N%3!<%I$Ke(B passed_block e$B$r%A%’%C%/$9$k$h$&$KJQ99$9$kI,e(B
|e$BMW$,=P$F$-$F!$$A$g$C$H8=<BE*$8$c$J$$$N$G$9!%e(B
|
|e$B!v%U%l!<%`$r$=$N;~$@$1$$$8$C$A$c$&!$$H$$$&2sHr<jCJ$,$”$k$h$&$J!$e(B
|e$B!!7y$J$H$3$m$KGH5Z$7$=$&$J!%e(B
|
|
|e$B!!Nc$($P!$e(Brb_iterate e$B$Oe(B obsolete e$B$K$7$F$7$^$C$F!J@)8BIU$-$GB8:_!K!$e(B
|rb_block_call e$B$r;H$&$h$&$K$7$F2<$5$$!$$H%I%-%e%a%s%H$9$k$N$O$I$s$J$b$s$Ge(B
|e$B$7$g$&$+!%e(B

e$B$^$“!”$=$l$O$=$l$G9=$$$^$;$s!#e(B

e$B1sF#$G$9!#e(B

2009/05/22 5:39 SASADA Koichi [email protected]:

Yusuke ENDOH wrote::

e$B$=$3$G!"0J2<$N$h$&$K!"e(Byielder_new_i e$B$Ge(B proc e$B%a%=%C%I$r8F$V$3$H$Ge(B
e$B%P%0$OD>$j$^$7$?!#e(B

e$B!!;w$?$h$&$JOC$J$s$G$9$,!$$=$b$=$be(B rb_iterate e$B$r;H$&>lLL$8$c$J$5$=$&$J!%e(B

e$B3N$+$K!#$5$5$@$5$s$N%Q%C%A$G$bD>$k$3$H$r3NG’$7$^$7$?!#e(B

e$BNc$($P!$e(Brb_iterate e$B$Oe(B obsolete e$B$K$7$F$7$^$C$F!J@)8BIU$-$GB8:_!K!$e(B
rb_block_call e$B$r;H$&$h$&$K$7$F2<$5$$!$$H%I%-%e%a%s%H$9$k$N$O$I$s$J$b$s$Ge(B
e$B$7$g$&$+!%e(B

e$B$J$k$[$I!"e(Brb_block_call e$B$OI,$:%a%=%C%I$r8F$S=P$9$+$iBg>fIWe(B
e$B$J$s$G$9$M!#e(B

e$B%I%-%e%a%s%H=$@50F$N%Q%C%A$G$9!#e(B

Index: README.EXT

— README.EXT (revision 23508)
+++ README.EXT (working copy)
@@ -1159,11 +1159,22 @@

** Control Structure

  • VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void
    *arg2)
  • VALUE rb_block_call(VALUE recv, ID mid, int argc, VALUE * argv,
  •     VALUE (*func) (ANYARGS), VALUE data2)
    

+Calls a method on the recv, with the method name specified by the
+symbol mid, supplying func as the block. func will receive the
+value from yield as the first argument, data2 as the second, and
+argc/argv as the third/fourth arguments.
+

  • [OBSOLETE] VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE
    (*func2)(), void *arg2)

Calls the function func1, supplying func2 as the block. func1 will be
called with the argument arg1. func2 receives the value from yield as
the first argument, arg2 as the second argument.
+
+When rb_iterate is used in 1.9, func1 has to call some Ruby-level
method.
+This function is obsolete since 1.9; use rb_block_call instead.

VALUE rb_yield(VALUE val)

Index: README.EXT.ja

— README.EXT.ja (revision 23508)
+++ README.EXT.ja (working copy)
@@ -1258,11 +1258,22 @@

** e$B@)8f9=B$e(B

-VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE
arg2)
+VALUE rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,

  •    VALUE (*func) (ANYARGS), VALUE data2)
    
  • funce$B$r%V%m%C%/$H$7$F@_Dj$7e(B, obje$B$r%l%7!<%Pe(B,
    argce$B$He(Bargve$B$r0ze(B

  • e$B?t$H$7$Fe(Bmide$B%a%=%C%I$r8F$S=P$9e(B.
    funce$B$OBh0l0z?t$Ke(Byielde$B$5$l$?e(B

  • e$BCMe(B, e$BBhFs0z?t$Ke(Bdata2, e$BBh;0e(B,
    e$BBh;M0z?t$Ke(Bargce$B$He(Bargve$B$r<u$1<h$ke(B.

+[OBSOLETE] VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE
(*func2)(), VALUE arg2)
+
func2e$B$r%V%m%C%/$H$7$F@_Dj$7e(B,
func1e$B$r%$%F%l!<%?$H$7$F8F$V!%e(B
func1e$B$K$Oe(B arg1e$B$,0z?t$H$7$FEO$5$le(B,
func2e$B$K$OBhe(B1e$B0z?t$K%$%F%l!<e(B
e$B%?$+$iM?$($i$l$?CMe(B, e$BBhe(B2e$B0z?t$Ke(Barg2e$B$,EO$5$l$k!%e(B
+

  • 1.9e$B$Ge(Brb_iteratee$B$r;H$&>l9g$Oe(B,
    func1e$B$NCf$Ge(BRubye$B%l%Y%k$N%a%=%C%Ie(B
  • e$B$r8F$S=P$5$J$1$l$P$J$i$J$$e(B.
  • 1.9e$B$Ge(Bobsoletee$B$H$J$C$?e(B.
    e$BBe$o$j$Ke(Brb_block_calle$B$,MQ0U$5$l$?e(B.

VALUE rb_yield(VALUE val)

e$B!!$5$5$@$G$9!%e(B

e$B!!JV;v$,?oJ,CY$/$J$C$F$7$^$C$F$9$_$^$;$s!%e(B

Yusuke ENDOH wrote::

e$B$J$k$[$I!"e(Brb_block_call e$B$OI,$:%a%=%C%I$r8F$S=P$9$+$iBg>fIWe(B
e$B$J$s$G$9$M!#e(B

e$B%I%-%e%a%s%H=$@50F$N%Q%C%A$G$9!#e(B

e$B!!$h$m$7$$$+$H;W$$$^$7$?!%e(B

e$B%A%1%C%He(B #1501 e$B$,99?7$5$l$^$7$?!#e(B (by Yusuke E.)

e$B%9%F!<%?%9e(B Assignede$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r24094.

http://redmine.ruby-lang.org/issues/show/1501