Infinite recursive rb_block_call

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

[ruby-core:24794] e$B$H;w$?$h$&$JLdBj$O!"e(Brb_block_call
e$B$G$b5/$-$k$h$&$G$9!#e(B

$ ./ruby -e ’
class C
include Enumerable
alias :each :min
end
C.new.min

Segmentation fault

min e$B0J30$G$be(B Enumerable e$B$N%a%=%C%I$GBgDqMn$A$k$_$?$$$G$9!#e(B

rb_funcall_no_recursive e$B$r??;w$Fe(B rb_block_call_no_recursive
e$B$r:n$C$Fe(B
e$B8+$^$7$?!#e(B[ruby-dev:39592]
e$B$NAj8_:F5"$NLdBj$OF1$8$h$&$K$"$k$H;W$$$^$9!#e(B

e$B$3$NJ}?K$@$H$[$$9$Y$F$Ne(B rb_block_call
e$B$N8F$S=P$7$r=q$-49$($FLa$jCM$,e(B
Qundef
e$B$G$J$$$+$I$&$+%A%’%C%/$9$kI,MW$,$"$j$=$&$G$9!#2DFI@-$d@-G=$re(B
e$B5>@7$K$7$F$G$b!"$3$N$h$&$J0[>o$J%W%m%0%i%`$r5_:Q$9$Y$-$G$7$g$&$+e(B
(Qundef e$B$rJV$5$:D>@\Nc30$rEj$2$l$P$b$&>/$7$9$C$-$j$9$k!)e(B)

Index: enum.c

— enum.c (revision 25576)
+++ enum.c (working copy)
@@ -1101,7 +1101,10 @@
rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)result);
}
else {

  • rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)result);
  • VALUE ret = rb_block_call_no_recursive(obj, id_each, 0, 0, min_i,
    (VALUE)result, enum_min);
  • if (ret == Qundef) {
  •  rb_raise(rb_eRuntimeError, "recursive call to Enumerable#min");
    
  • }
    }
    if (result[0] == Qundef) return Qnil;
    return result[0];
    Index: vm_eval.c
    ===================================================================
    — vm_eval.c (revision 25576)
    +++ vm_eval.c (working copy)
    @@ -815,7 +815,48 @@
    return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
    }

+struct iter_method_arg_no_recursive {

  • struct iter_method_arg arg;
  • VALUE (*func)();
    +};

+static VALUE
+iterate_method_no_recursive(VALUE obj)
+{

  • const struct iter_method_arg_no_recursive * arg =
  •  (struct iter_method_arg_no_recursive *) obj;
    
  • rb_method_entry_t *me = rb_search_method_emtry(arg->arg.obj,
    arg->arg.mid);
  • rb_thread_t *th = GET_THREAD();
  • int call_status;
  • if (!me) return Qundef;
  • if (me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
  • me->def->body.cfunc.func == arg->func)
  • return Qundef;
  • call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
  • if (call_status != NOEX_OK) {
  • return Qundef;
  • }
  • stack_check();
  • iterate_method((VALUE) &arg->arg);
    +}

VALUE
+rb_block_call_no_recursive(VALUE obj, ID mid, int argc, VALUE * argv,

  •     VALUE (*bl_proc) (ANYARGS), VALUE data2,
    
  •     VALUE (*func)())
    

+{

  • struct iter_method_arg_no_recursive arg;
  • arg.arg.obj = obj;
  • arg.arg.mid = mid;
  • arg.arg.argc = argc;
  • arg.arg.argv = argv;
  • arg.func = func;
  • return rb_iterate(iterate_method_no_recursive, (VALUE)&arg,
    bl_proc, data2);
    +}

+VALUE
rb_each(VALUE obj)
{
return rb_call(obj, idEach, 0, 0, CALL_FCALL);

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

In message “Re: [ruby-dev:39593] infinite recursive rb_block_call”
on Fri, 30 Oct 2009 22:17:04 +0900, Yusuke ENDOH [email protected]
writes:

|e$B$3$NJ}?K$@$H$[$$9$Y$F$Ne(B rb_block_call e$B$N8F$S=P$7$r=q$-49$($FLa$jCM$,e(B
|Qundef e$B$G$J$$$+$I$&$+%A%'%C%/$9$kI,MW$,$“$j$=$&$G$9!#2DFI@-$d@-G=$re(B
|e$B5>@7$K$7$F$G$b!”$3$N$h$&$J0[>o$J%W%m%0%i%`$r5_:Q$9$Y$-$G$7$g$&$+e(B
|(Qundef e$B$rJV$5$:D>@\Nc30$rEj$2$l$P$b$&>/$7$9$C$-$j$9$k!)e(B)

e$B$=$N2ACM$O$J$$$H;W$$$^$9!#e(B