summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Momchilov <alexander.momchilov@shopify.com>2026-05-13 17:13:53 -0400
committerTakashi Kokubun <takashikkbn@gmail.com>2026-05-14 11:58:17 -0700
commit977e7fd3927a3c5da2bacce03798fcc0b44ab4bf (patch)
tree84ecc373a1dc73b55b1dc6d56608abd31b4b2bdc
parentcd38f6c5e141f18de1001b36baf3f18162d3d333 (diff)
[Bug #22070] Fix segfault in `Thread.each_caller_location`ruby_4_0
-rw-r--r--test/ruby/test_backtrace.rb10
-rw-r--r--vm_backtrace.c2
2 files changed, 11 insertions, 1 deletions
diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb
index dad7dfcb55..332d76c58e 100644
--- a/test/ruby/test_backtrace.rb
+++ b/test/ruby/test_backtrace.rb
@@ -191,6 +191,16 @@ class TestBacktrace < Test::Unit::TestCase
assert_equal(cl.map(&:to_s), ary.map(&:to_s))
end
+ def test_each_caller_location_single_cfunc_frame
+ assert_normal_exit <<~'RUBY'
+ tap { Thread.each_caller_location(1, 1) { |loc| loc.label } }
+ RUBY
+
+ cl = nil; ary = []
+ tap { cl = caller_locations(1, 1); Thread.each_caller_location(1, 1) { |x| ary << x } }
+ assert_equal(cl.map(&:to_s), ary.map(&:to_s))
+ end
+
def test_caller_locations_first_label
def self.label
caller_locations.first.label
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 07d2e33e32..02d5b4410d 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -757,7 +757,7 @@ rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long start_fram
bt_backpatch_loc(backpatch_counter, loc, cfp->iseq, cfp->pc);
RB_OBJ_WRITTEN(btobj, Qundef, cfp->iseq);
if (do_yield) {
- bt_yield_loc(loc - backpatch_counter, backpatch_counter, btobj);
+ bt_yield_loc(loc - backpatch_counter + 1, backpatch_counter, btobj);
}
break;
}