From b62753246eba4940f82a81736fc09b6517fa3965 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 10 Sep 2025 19:53:13 -0400 Subject: [PATCH] Fix out-of-bounds read in rb_location_ary_to_backtrace rb_location_ary_to_backtrace was not checking the length of the array before reading the first element. It can be reproduced by the following script: begin raise rescue $@ = [] end With assertions enabled, it crashes with: internal/array.h:143: Assertion Failed: RARRAY_AREF:i < RARRAY_LEN(ary) ruby 3.5.0dev (2025-09-10T19:01:16Z array-aref-assert-.. c431de0c64) +PRISM [arm64-darwin24] -- Crash Report log information -------------------------------------------- See Crash Report log file in one of the following locations: * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports. -- Control frame information ----------------------------------------------- c:0004 p:---- s:0015 e:000014 CFUNC :set_backtrace c:0003 p:0013 s:0012 e:000009 RESCUE test.rb:4 c:0002 p:0004 s:0006 e:000005 EVAL test.rb:1 [FINISH] c:0001 p:0000 s:0003 E:001bb0 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- test.rb:1:in '
' test.rb:4:in 'rescue in
' test.rb:4:in 'set_backtrace' -- Threading information --------------------------------------------------- Total ractor count: 1 Ruby thread count for this ractor: 1 -- C level backtrace information ------------------------------------------- miniruby(rb_vm_bugreport+0xb88) [0x1002adb88] vm_dump.c:1175 miniruby(rb_vm_bugreport) (null):0 miniruby(rb_assert_failure_detail+0xd4) [0x1003fbf90] error.c:1215 miniruby(rb_assert_failure_detail+0x0) [0x1003fbebc] error.c:1191 miniruby(rb_assert_failure) (null):0 miniruby(RARRAY_AREF+0x20) [0x1003f82c8] internal/array.h:143 miniruby(rb_keyword_error_new.cold.2) class.c:2867 miniruby(rb_keyword_error_new.cold.4) (null):0 miniruby(rb_location_ary_to_backtrace+0x244) [0x1002a8a60] internal/array.h:143 miniruby(RB_TEST+0x0) [0x1000ba648] error.c:2111 miniruby(exc_set_backtrace) error.c:2112 miniruby(vm_call0_body+0x7d0) [0x1002a414c] vm_eval.c:164 miniruby(rb_vm_call0+0x100) [0x100286ee4] vm_eval.c:101 miniruby(set_backtrace+0xfc) [0x1000c88a4] eval_error.c:75 miniruby(rb_gvar_set_entry+0x10) [0x100269230] variable.c:990 miniruby(rb_gvar_set) variable.c:1021 miniruby(vm_exec_core+0x1258) [0x10027a744] insns.def:319 miniruby(rb_vm_exec+0x324) [0x100277a8c] vm.c:2666 miniruby(rb_ec_exec_node+0x74) [0x1000c4a38] eval.c:282 miniruby(ruby_run_node+0x64) [0x1000c4968] eval.c:320 miniruby(rb_main+0x1c) [0x100000980] main.c:42 miniruby(main) main.c:62 --- vm_backtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm_backtrace.c b/vm_backtrace.c index cc8607b2d7..aaa0b5051c 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -858,7 +858,7 @@ rb_backtrace_to_location_ary(VALUE self) VALUE rb_location_ary_to_backtrace(VALUE ary) { - if (!RB_TYPE_P(ary, T_ARRAY) || !rb_frame_info_p(RARRAY_AREF(ary, 0))) { + if (!RB_TYPE_P(ary, T_ARRAY) || RARRAY_LEN(ary) == 0 || !rb_frame_info_p(RARRAY_AREF(ary, 0))) { return Qfalse; }