Project

General

Profile

Actions

Bug #21198

open

Fiber::Scheduler#blocking_operation_wait crash due to stack-use-after-return

Added by peterzhu2118 (Peter Zhu) 6 days ago. Updated 6 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:121443]

Description

The Fiber::Scheduler#blocking_operation_wait method is passed a proc through the rb_fiber_scheduler_blocking_operation_wait function. This function stack allocates the arguments used for the proc (source). If this proc is captured anywhere, then calling it again will illegally read from and write to stack space.

The following script demonstrates this issue using the test/fiber/scheduler.rb scheduler:

require_relative "test/fiber/scheduler"

class MyScheduler < Scheduler
  def blocking_operation_wait(work)
    super

    $work = work
  end
end

scheduler = MyScheduler.new
Fiber.set_scheduler(scheduler)

require "tempfile"

Fiber.schedule do
  file = Tempfile.new
  file.write("hello world!")
  $work.call
end

scheduler.run

Crashes with:

test.rb:19: [BUG] Bus Error at 0xce0f57696add0045
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +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:0003 p:---- s:0010 e:000009 IFUNC 
c:0002 p:0017 s:0007 e:000006 BLOCK  test.rb:19 [FINISH]
c:0001 p:---- s:0003 e:000002 DUMMY  [FINISH]

-- Ruby level backtrace information ----------------------------------------
test.rb:19:in 'block in <main>'

-- Threading information ---------------------------------------------------
Total ractor count: 1
Ruby thread count for this ractor: 1
Note that the Fiber scheduler is enabled

-- Machine register context ------------------------------------------------
  x0: 0x000000010063a5f0  x1: 0x000000014b80ce00  x2: 0x0000000000000000
  x3: 0x000000014b60f060  x4: 0x0000000000000000  x5: 0x0000000000000000
  x6: 0x0000000000000004  x7: 0x0000000000000000 x18: 0x0000000000000000
 x19: 0x000000014b6a4840 x20: 0xce0f57696add0045 x21: 0x000000010063a5f0
 x22: 0x000000014b60f060 x23: 0x0000000000000000 x24: 0x000000014b60f998
 x25: 0x0000000000014273 x26: 0x000000014b60f060 x27: 0x000000014b60f060
 x28: 0x000000014b80ce00  lr: 0x0000000100d881d8  fp: 0x000000011bb039f0
  sp: 0x000000011bb03980

-- C level backtrace information -------------------------------------------
SEGV received in BUS handler
[1]    52599 abort      ruby test.rb

Updated by ioquatix (Samuel Williams) 6 days ago

A solution to this would be to invalidate the proc afterwards. I don't know if this is possible but I can take a look.

Actions

Also available in: Atom PDF

Like0
Like0