Enumerator with certain built-in methods dumps core

e$B1sF#$H?=$7$^$9!#e(B

e$B0J2<$Ge(B 1.9 e$B$,Mn$A$^$9!#e(B

$ ./ruby -e ‘Module.enum_for(:new).next’
[BUG] Segmentation fault
ruby 1.9.0 (2008-03-25 revision 15837) [i686-linux]

– control frame ----------
c:0006 p:---- s:0011 b:0011 l:000010 d:000010 CFUNC :initialize
c:0005 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :new
c:0004 p:---- s:0007 b:0007 l:000006 d:000006 CFUNC :call
c:0003 p:---- s:0005 b:0005 l:000004 d:000004 CFUNC :each
c:0002 p:---- s:0003 b:0003 l:001888 d:000002 IFUNC
c:0001 p:---- s:0001 b:-001 l:000000 d:000000 ------

DBG> : “:0:in new'" DBG> : ":0:incall’”
DBG> : “:0:in `each’”
– backtrace of native function call (Use addr2line) –
0x80fb525
0x81235ce
0x812362b
0x80c9880
0xffffe440
0x8059f27
0x8080159
0x80fa425
0x805b58d
0x805b8b0
0x805ba3c
0x8080dda
0x80f19de
0x80fa425
0x8060f7e
0x80f19de
0x80fa425
0x805b58d
0x805b8b0
0x805dc43
0x805a258
0x805a2cf
0x81211fd
0x80fa425
0x805b58d
0x805b8b0
0x805dc43
0x805a258
0x805a2cf
0x812115f
0x80f96f0
0x80f992e
0x81009c5
0x805ab9f
0x805e250
0x8058641
0xb7dadea8
0x8058551

e$B%"%!<%H$7$^$7$?e(B

e$B%3%s%H%m!<%k%9%?%C%/$N:G=i$Ge(B module_eval e$B$J$I$,8F$P$l$k$H!"e(B
ruby e$B%l%Y%k$Ne(B cfp e$B$,B8:_$7$J$$$?$a!“L58z$Je(B cfp
e$B$K%”%/%;%9e(B
e$B$9$k$h$&$G$9!#e(B

e$B$[$+$K$b0J2<$N%W%m%0%i%`$?$A$GMn$A$^$9!#e(B

e$B!ye(B eval.c e$B$GMn$A$ke(B

  • Object.enum_for(:class_eval).next

  • Fiber.new(&Object.method(:class_eval)).resume(“foo”)

  • Thread.new(“foo”, &Object.method(:class_eval)).join

  • “foo”.enum_for(:instance_eval).next

  • Fiber.new(&“foo”.method(:instance_eval)).resume(“foo”)

  • Thread.new(“foo”, &“foo”.method(:instance_eval)).join

  • enum_for(:eval, “foo”).next

  • Fiber.new(&Object.method(:eval)).resume(“foo”)

  • Thread.new(“foo”, &Object.method(:eval)).join

  • enum_for(:local_variables).next

  • enum_for(:block_given?).next

e$B!ye(B ruby_cref/SCOPE_TEST/SCOPE_CHECK/SCOPE_SET e$B$GMn$A$ke(B

  • enum_for(:binding).next
  • Module.enum_for(:nesting).next
  • Module.enum_for(:constants).next
  • Module.enum_for(:attr, :foo).next
  • Module.enum_for(:attr_reader, :foo).next
  • Module.enum_for(:attr_writer, :foo).next
  • Module.enum_for(:attr_accessor, :foo).next
  • Module.enum_for(:public).next
  • Module.enum_for(:protected).next
  • Module.enum_for(:private).next
  • module M; enum_for(:module_function).next; end

e$B!ye(B rb_backref_set/rb_backref_get e$B$GMn$A$ke(B

  • “abc”.enum_for(:[], /./).next
  • “abc”.enum_for(:scan, /./).next
  • “abc”.enum_for(:sub, /./).next
  • “abc”.enum_for(:gsub, /./).next
  • “abc”.enum_for(:split, /./).next
  • “abc”.enum_for(:partition, /./).next
  • “abc”.enum_for(:rpartition, /./).next

“abc”.enum_for(:scan, /./).next e$B$O<B:]$K;H$$$=$&$G$9!#e(B

eval.c e$B$@$11~5^=hCV$r:n$C$F$_$^$7$?$,!"$3$NJ}?K$@$He(B backref
e$B<~$j$Ge(B
e$B=$@5$,$?$/$5$sI,MW$=$&$G$9!#e(B
e$B:,K\E*$JBP:v$r8!F$$7$?J}$,$$$$$+$b$7$l$^$;$s!#e(B

e$B%3%s%H%m!<%k%9%?%C%/$N:G=i$K%@%_!<$Ne(B ruby

e$B%l%Y%k$N%U%l!<%`$r$*$/!)e(B

Index: eval.c

— eval.c (revision 15834)
+++ eval.c (working copy)
@@ -886,7 +886,7 @@
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp = th->cfp;
cfp = vm_get_ruby_level_cfp(th,
RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));

  • if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
  • if (cfp && GC_GUARDED_PTR_REF(cfp->lfp[0])) {
    return Qtrue;
    }
    else {
    @@ -1712,6 +1712,9 @@
    }
    else {
    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
  •  if (!cfp) {
    
  • rb_raise(rb_eArgError, “eval called at the stack bottom”);
  •  }
     th->base_block = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
     th->base_block->iseq = cfp->iseq;  /* TODO */
    
    }
    @@ -1851,8 +1854,9 @@
    *th->cfp->lfp = GC_GUARDED_PTR(&block);
    }
  • while (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
  • cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
  • cfp = vm_get_ruby_level_cfp(th, cfp);

  • if (!cfp) {

  • return (*func) (args);
    }

    stored_cref = (NODE *)vm_cfp_svar_get(th, cfp, 2);
    @@ -2612,6 +2616,8 @@
    vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
    int i;

  • if (!cfp) return ary;

  • while (1) {
    if (cfp->iseq) {
    for (i = 0; i < cfp->iseq->local_table_size; i++) {