[ruby-core:125811] [Ruby Bug#22125] IO::Buffer triggers use-after-free when it's freed/resized during enumeration
Issue #22125 has been reported by hanazuki (Kasumi Hanazuki). ---------------------------------------- Bug #22125: IO::Buffer triggers use-after-free when it's freed/resized during enumeration https://bugs.ruby-lang.org/issues/22125 * Author: hanazuki (Kasumi Hanazuki) * Status: Open * ruby -v: ruby 4.1.0dev (2026-06-23T09:56:24Z master 55945e5c98) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- The block passed to `IO::Buffer#each` can free or resize the receiver (or its parent buffer when the reciver is a slice), which invalidates the memory region being iterated. The next iteration causes use-after-free. repro: ``` ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.free }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.resize(20) }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b1=b.slice; b1.each {|_, v| p v; b.free }' # No use-after-free but I think those should be errors too ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b1=b.slice; b1.each {|_, v| p v; b1.free }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.transfer }' ``` same for `#each_byte`. -- https://bugs.ruby-lang.org/
Issue #22125 has been updated by kou (Kouhei Sutou). We're already discussing how to fix this case in https://github.com/ruby/ruby/pull/17398 . ---------------------------------------- Bug #22125: IO::Buffer triggers use-after-free when it's freed/resized during enumeration https://bugs.ruby-lang.org/issues/22125#change-117739 * Author: hanazuki (Kasumi Hanazuki) * Status: Open * ruby -v: ruby 4.1.0dev (2026-06-23T09:56:24Z master 55945e5c98) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- The block passed to `IO::Buffer#each` can free or resize the receiver (or its parent buffer when the reciver is a slice), which invalidates the memory region being iterated. The next iteration causes use-after-free. repro: ``` ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.free }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.resize(20) }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b1=b.slice; b1.each {|_, v| p v; b.free }' # No use-after-free but I think those should be errors too ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b1=b.slice; b1.each {|_, v| p v; b1.free }' ./miniruby -ve 'b=IO::Buffer.for("ruby"*10).dup; b.each {|_, v| p v; b.transfer }' ``` same for `#each_byte`. -- https://bugs.ruby-lang.org/
participants (2)
-
hanazuki (Kasumi Hanazuki) -
kou (Kouhei Sutou)