[ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
From:
"chucke (Tiago Cardoso) via ruby-core" <ruby-core@...>
Date:
2025-02-13 00:11:01 UTC
List:
ruby-core #120961
Issue #21131 has been reported by chucke (Tiago Cardoso).
----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131
* Author: chucke (Tiago Cardoso)
* Status: Open
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
I found an odd situation, when using IO.copy_stream with a File writer quack class, where the data passed to #write somehow ends overwritten, despite the instance being duped.
class ProcIO
def initialize(block)
@block = block
end
# Implementation the IO write protocol, which yield the given chunk to +@block+.
def write(data)
@block.call(data.dup)
data.bytesize
end
end
rng = Random.new(42)
body = Tempfile.new("ruby-bug", binmode: true)
body.write(rng.bytes(16_385))
body.rewind
payload = []
block = ->(data){ payload << data.dup }
IO.copy_stream(body, ProcIO.new(block))
body.rewind
if payload.join != body.read
puts "it's a bug"
end
if you use the debugger, you'll see that the first yielded chunk has the correct bytes when yielded the first time, but when the second 1 byte chunk is yielded (IO.copy_stream reads in chunks of 16384 bytes), the first chunk string value suddenly changes. This should not happen, as the first yielded chunk was a string duped from the string yielded by IO.copy_stream (which is expected to be a buffer).
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/