Fix out-of-bounds read in require when $LOADED_FEATURES is modified

The following script causes an out-of-bounds read on the $LOADED_FEATURES
array when it is modified by another thread:

    require "tempfile"
    PATH = Tempfile.create(["test", ".rb"]).path

    2.times.map do
      Thread.new do
        20.times do
          require PATH
          $LOADED_FEATURES.delete_if { |p| p == PATH }
        end
      end
    end.each(&:join)

Crashes with:

    internal/array.h:143: Assertion Failed: RARRAY_AREF:i < RARRAY_LEN(ary)
    ruby 3.5.0dev (2025-09-10T18:47:06Z array-aref-assert-.. 765a3fd01c) +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:0005 p:---- s:0019 e:000018 CFUNC  :require
    c:0004 p:0005 s:0014 e:000013 BLOCK  test.rb:19
    c:0003 p:0024 s:0011 e:000010 METHOD <internal:numeric>:257
    c:0002 p:0005 s:0006 e:000005 BLOCK  test.rb:18 [FINISH]
    c:0001 p:---- s:0003 e:000002 DUMMY  [FINISH]

    -- Ruby level backtrace information ----------------------------------------
    test.rb:18:in 'block (2 levels) in <main>'
    <internal:numeric>:257:in 'times'
    test.rb:19:in 'block (3 levels) in <main>'
    test.rb:19:in 'require'

    -- Threading information ---------------------------------------------------
    Total ractor count: 1
    Ruby thread count for this ractor: 2

    -- C level backtrace information -------------------------------------------
    miniruby(rb_vm_bugreport+0xb88) [0x100f3f1d4] vm_dump.c:1175
    miniruby(rb_vm_bugreport) (null):0
    miniruby(rb_assert_failure_detail+0xd4) [0x10108d920] error.c:1215
    miniruby(rb_assert_failure_detail+0x0) [0x10108d84c] error.c:1191
    miniruby(rb_assert_failure) (null):0
    miniruby(rb_ary_pop.cold.9+0x0) [0x101087198] internal/array.h:143
    miniruby(RARRAY_AREF) (null):0
    miniruby(rb_ary_pop.cold.7) array.c:1443
    miniruby(rb_feature_p+0x720) [0x100dbe28c] internal/array.h:143
    miniruby(search_required+0x2cc) [0x100dbcb78] load.c:1203
    miniruby(require_internal+0x144) [0x100dbd108] load.c:1434
    miniruby(rb_require_string_internal+0x78) [0x100dbc6bc] load.c:1581
    miniruby(rb_require_string+0x20) [0x100dbc56c] load.c:1567
    miniruby(rb_f_require) load.c:1160
    miniruby(vm_call_cfunc_with_frame_+0xe8) [0x100f2e998] vm_insnhelper.c:3873
    miniruby(vm_sendish+0x718) [0x100f08b20]
    miniruby(vm_exec_core+0x6044) [0x100f10a94]
    miniruby(rb_vm_exec+0x170) [0x100f08e3c] vm.c:2639
    miniruby(vm_invoke_proc+0x200) [0x100f1f564] vm.c:1669
    miniruby(thread_do_start_proc+0x2f4) [0x100ed8420] thread.c:605
    miniruby(thread_start_func_2+0x37c) [0x100ed7714] thread.c:622
    miniruby(call_thread_start_func_2+0x18) [0x100eda144] thread_pthread.c:2234
    miniruby(nt_start) thread_pthread.c:2279
    /usr/lib/system/libsystem_pthread.dylib(_pthread_start+0x88) [0x19c0e7c0c]
This commit is contained in:
Peter Zhu committed 2025-09-10 15:01:16 -04:00
1 parent f3b5cb77bd
commit c431de0c64
1 file changed
+1
+1
View File
@@ -630,6 +630,7 @@ rb_feature_p(vm_ns_t *vm_ns, const char *feature, const char *ext, int rb, int e
index = rb_darray_get(feature_indexes, i);
}
if (index >= RARRAY_LEN(features)) continue;
v = RARRAY_AREF(features, index);
f = StringValuePtr(v);
if ((n = RSTRING_LEN(v)) < len) continue;