遠藤です。

[ruby-core:24794] と似たような問題を探してみましたが、かなりありそうです。

$ ./ruby -e '
  class Symbol
    include Enumerable
    alias to_enum zip
  end
  :each.zip(:each) { }
'
Segmentation fault


$ ruby19 -e '
  class Hash
    alias default []
  end
  {}[1]
'
Segmentation fault


$ ruby19 -e '
  class Object
    alias to_open open
    public :to_open
  end
  o = Object.new
  eval("open(#{ (["o"] * 10000).join(",") })") # open(o, o, o, o, ...)
'
Segmentation fault


$ ruby19 -e '
  class Time
    def to_str
    end
  end
  Time.now <=> ""
'
Segmentation fault


matz ruby では、この手のバグはちまちまと潰していくということで
いいのでしょうか。
最後のは相互再帰するので rb_funcall_no_recursive では救えそうに
ありません。<=> での相互再帰は多分結構ありそうですが、どうしま
しょう。


Index: enum.c
===================================================================
--- enum.c	(revision 25576)
+++ enum.c	(working copy)
@@ -1745,7 +1745,11 @@
     if (!allary) {
 	CONST_ID(conv, "to_enum");
 	for (i=0; i<argc; i++) {
-	    argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
+	    VALUE sym = ID2SYM(id_each);
+	    argv[i] = rb_funcall_no_recursive(argv[i], conv, 1, &sym, enum_zip);
+	    if (argv[i] == Qundef) {
+		rb_raise(rb_eRuntimeError, "recursive call to Enumerable#zip");
+	    }
 	}
     }
     if (!rb_block_given_p()) {
Index: io.c
===================================================================
--- io.c	(revision 25576)
+++ io.c	(working copy)
@@ -5589,7 +5589,10 @@
 	}
     }
     if (redirect) {
-	VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
+	VALUE io = rb_funcall_no_recursive(argv[0], to_open, argc-1, argv+1,
rb_f_open);
+	if (io == Qundef) {
+	    rb_raise(rb_eRuntimeError, "recursive call to Kernel#open");
+	}

 	if (rb_block_given_p()) {
 	    return rb_ensure(rb_yield, io, io_close, io);
Index: hash.c
===================================================================
--- hash.c	(revision 25576)
+++ hash.c	(working copy)
@@ -494,7 +494,11 @@
     VALUE val;

     if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
-	return rb_funcall(hash, id_default, 1, key);
+	VALUE ret = rb_funcall_no_recursive(hash, id_default, 1, &key, rb_hash_aref);
+	if (ret == Qundef) {
+	    rb_raise(rb_eRuntimeError, "recursive call to Hash#[]");
+	}
+	return ret;
     }
     return val;
 }

-- 
Yusuke ENDOH <mame / tsg.ne.jp>