From: "bladenkerst (Brad Sumersford)" Date: 2013-02-08T11:33:20+09:00 Subject: [ruby-core:52022] [ruby-trunk - Bug #7802][Open] Ruby crashes when detect is called while executing the ensure callback given to rb_ensure Issue #7802 has been reported by bladenkerst (Brad Sumersford). ---------------------------------------- Bug #7802: Ruby crashes when detect is called while executing the ensure callback given to rb_ensure https://bugs.ruby-lang.org/issues/7802 Author: bladenkerst (Brad Sumersford) Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: 1.9.3 Conditions: - rb_ensure(cb, cb_args, ensure, ensure_args) is used from C API - cb raises an exception - ensure calls Enumerable#detect and detect finds an element Sample code: # ensured.c #include "ruby.h" static VALUE rubyEnsuredBegin(VALUE object) { return rb_funcall(object, rb_intern("try_method"), 0); } static VALUE rubyEnsure(VALUE object) { return rb_funcall(object, rb_intern("ensured_method"), 0); } static VALUE rubyEnsured(VALUE module, VALUE object) { VALUE result = rb_ensure( rubyEnsuredBegin, object, rubyEnsure, object ); return result; } void Init_ensured() { rb_define_method(rb_mKernel, "ensured", rubyEnsured, 1); } # test_ensured.rb require_relative 'ensured' class TestObject def try_method raise "error raised in rb_ensure" end def ensured_method # Returning true in the detect block will # call rb_iter_break() which will cause # Ruby to crash when the exception resumes # unwinding the stack [1].detect { |i| ARGV[0] == 'crash' } # This line still gets executed puts 'after detect' end end begin ensured(TestObject.new) rescue puts $! end __END__ $ ruby test_ensured.rb after detect error raised in rb_ensure $ ruby test_ensured.rb crash after detect test_ensured.rb: [BUG] Segmentation fault ruby 1.9.3p385 (2013-02-06 revision 39114) [x86_64-darwin10.8.0] -- Control frame information ----------------------------------------------- c:0004 p:0030 s:0009 b:0009 l:000398 d:000008 BLOCK c:0003 p:0047 s:0006 b:0006 l:000398 d:000b18 EVAL test_ensured.rb:20 c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH c:0001 p:0000 s:0002 b:0002 l:000398 d:000398 TOP Reproduced on the following system: $ uname -a Linux lion 2.6.32-5-686 #1 SMP Sun Sep 23 09:49:36 UTC 2012 i686 GNU/Linux $ ruby -v ruby 1.9.3p327 (2012-11-10 revision 37606) [i686-linux] AND $ uname -v Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 $ ruby -v ruby 1.9.3p385 (2013-02-06 revision 39114) [x86_64-darwin10.8.0] The use case for the above example is testing a C extension with Mocha (or other mocking library) that uses rb_ensure and does regular rb_funcalls to the Ruby stdlib. -- http://bugs.ruby-lang.org/