Ensure IO.copy_stream buffer is an independent string

Otherwise, changes to the buffer by the destination write method
could result in data changing for supposedly independent strings.

Fixes [Bug #21131]
This commit is contained in:
Jeremy Evans 2025-02-17 17:23:14 -08:00
parent 6e510d78c0
commit f423f6e10c
Notes: git 2025-02-19 01:18:32 +00:00
2 changed files with 29 additions and 0 deletions

1
io.c
View File

@ -13139,6 +13139,7 @@ copy_stream_fallback_body(VALUE arg)
while (1) {
long numwrote;
long l;
rb_str_make_independent(buf);
if (stp->copy_length < (rb_off_t)0) {
l = buflen;
}

View File

@ -1141,6 +1141,34 @@ class TestIO < Test::Unit::TestCase
}
end
def test_copy_stream_dup_buffer
bug21131 = '[ruby-core:120961] [Bug #21131]'
mkcdtmpdir do
dst_class = Class.new do
def initialize(&block)
@block = block
end
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 = []
IO.copy_stream(body, dst_class.new{payload << it})
body.rewind
assert_equal(body.read, payload.join, bug21131)
ensure
body&.close
end
end
def test_copy_stream_write_in_binmode
bug8767 = '[ruby-core:56518] [Bug #8767]'
mkcdtmpdir {