Bug #22075
closedheap-use-after-free in `rb_vm_ci_lookup` under parallel Ractors
Description
Environment¶
ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [aarch64-linux]- Also reproduced on
ruby 4.0.4 ... [x86_64-linux].
Summary¶
Under a parallel Ractor pool, a GC sweep on one Ractor frees a T_DATA object while rb_vm_ci_lookup on another Ractor reads that freed heap memory. Pure-Ruby code triggers it; the VM crashes (SIGSEGV).
Reproduction¶
No minimal script isolated yet.
Reproduced with the rigor project at tag v0.1.7 (https://github.com/rigortype/rigor/tree/v0.1.7).
-
Build Ruby + native gems with AddressSanitizer:
./configure --disable-yjit \ cflags="-fsanitize=address -fno-sanitize-address-use-after-scope -g -O1" \ cppflags="-fsanitize=address" LDFLAGS="-fsanitize=address" -
Run a spec that drives a 2-worker Ractor pool:
ASAN_OPTIONS="detect_leaks=0 detect_stack_use_after_return=0 halt_on_error=0" \ RIGOR_INCLUDE_RACTOR_POOL=1 \ bundle exec rspec spec/rigor/analysis/runner_pool_spec.rb
CI failure: https://github.com/rigortype/rigor/actions/runs/26123249293/job/76830355801
Expected¶
Pure-Ruby code on a Ractor pool runs to completion or raises a Ruby exception. It does not corrupt the heap.
Actual¶
SIGSEGV (≈70% of runs without a sanitizer; crash site varies).
AddressSanitizer (Ruby 4.0.5, aarch64-linux, 3 Ractors):
ERROR: AddressSanitizer: heap-use-after-free
READ of size 4
rb_vm_ci_lookup vm_method.c:699
vm_ci_new_ vm_callinfo.h:219
vm_ci_new_runtime_ vm_callinfo.h:240
vm_search_super_method vm_insnhelper.c:5152 (a Ruby `super` call)
freed by:
rb_gc_impl_free gc/default/default.c:8279
rb_data_free gc.c:1205
rb_gc_obj_free gc.c:1351
gc_sweep_plane gc/default/default.c:3510
previously allocated by:
rb_data_typed_object_zalloc gc.c:1131
rbs_new_location2 (rbs gem C extension)
SUMMARY: AddressSanitizer: heap-use-after-free vm_method.c:699 in rb_vm_ci_lookup
The same line also surfaces as heap-buffer-overflow.
Original CI [BUG] (Ruby 4.0.4, x86_64-linux), same path:
[BUG] Segmentation fault
vm_ci_hash <- rb_st_update <- rb_vm_ci_lookup (vm_method.c:712)
<- vm_ci_new_runtime_ <- vm_search_super_method
Total ractor count: 5
Notes¶
- ThreadSanitizer reports nothing — it cannot follow the M:N scheduler.
- Both ASAN stacks show
thread T0because the M:N scheduler multiplexes Ractors onto native threads; the run uses 3 Ractors. - The free path is a plain GC sweep (
gc_sweep_plane→rb_data_free), no finalizer.