Bug #21977
openRuby::Box crash with `RUBY_BOX=1` via `Binding` refinement, `UnboundMethod#bind_call`, and `Symbol#to_proc`
Description
Summary¶
I found a reproducible interpreter crash when Ruby is run with RUBY_BOX=1.
A refinement on Binding, combined with UnboundMethod#bind_call and Symbol#to_proc, causes Ruby to abort with:
[BUG] BUG: Local ep without cme/box, flags: 66660087
I reproduced this on:
ruby 4.1.0dev (2026-03-24T21:47:14Z master 30dcc2a082) +PRISM [x86_64-linux]
Follow-up validation confirmed an important discriminator: replacing map(&:to_s) with an explicit block such as map { _1.to_s } avoids the crash. The currently available evidence therefore points to a box/frame bookkeeping bug in the Symbol#to_proc path that reaches an explicit internal rb_bug(...) assertion, not to confirmed memory corruption.
PoC¶
using Module.new {
refine ::Binding do
def eval_methods
::Kernel.instance_method(:methods).bind_call(receiver)
end
end
}
p binding.eval_methods.map(&:to_s)
Run:
RUBY_BOX=1 ./miniruby -e '
using Module.new {
refine ::Binding do
def eval_methods
::Kernel.instance_method(:methods).bind_call(receiver)
end
end
}
p binding.eval_methods.map(&:to_s)
'
Observed result:
[BUG] BUG: Local ep without cme/box, flags: 66660087
ruby 4.1.0dev (2026-03-24T21:47:14Z master 30dcc2a082) +PRISM [x86_64-linux]
Crashed while printing bug report
Important discriminator:
p binding.eval_methods.map { _1.to_s }
Replacing map(&:to_s) with an explicit block avoids the crash, which strongly suggests that the failure depends specifically on the Symbol#to_proc path rather than map in general.
Impact¶
The currently confirmed impact is denial of service in processes using Ruby::Box with RUBY_BOX=1.
Confirmed claim:
- reliable interpreter abort
- trigger requires
RUBY_BOX=1 - trigger depends specifically on the
Symbol#to_procpath in this setup
Current non-claims:
- no confirmed memory corruption
- no confirmed sandbox escape
- no confirmed privilege escalation
- no confirmed arbitrary code execution
This report should remain separate from the Ruby::Box double-free issue, because the trigger path, failure mode, and currently demonstrated impact are different.
Updated by mame (Yusuke Endoh) about 21 hours ago
- Status changed from Open to Assigned
- Assignee set to tagomoris (Satoshi Tagomori)