8000 Ensure IO.copy_stream buffer is an independent string · github/ruby@f423f6e · GitHub
[go: up one dir, main page]

Skip to content

Commit f423f6e

Browse files
committed
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]
1 parent 6e510d7 commit f423f6e

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13139,6 +13139,7 @@ copy_stream_fallback_body(VALUE arg)
1313913139
while (1) {
1314013140
long numwrote;
1314113141
long l;
13142+
rb_str_make_independent(buf);
1314213143
if (stp->copy_length < (rb_off_t)0) {
1314313144
l = buflen;
1314413145
}

test/ruby/test_io.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,34 @@ def test_copy_stream_pathname_to_pathname
11411141
}
11421142
end
11431143

1144+
def test_copy_stream_dup_buffer
1145+
bug21131 = '[ruby-core:120961] [Bug #21131]'
1146+
mkcdtmpdir do
1147+
dst_class = Class.new do
1148+
def initialize(&block)
1149+
@block = block
1150+
end
1151+
1152+
def write(data)
1153+
@block.call(data.dup)
1154+
data.bytesize
1155+
end
1156+
end
1157+
1158+
rng = Random.new(42)
1159+
body = Tempfile.new("ruby-bug", binmode: true)
1160+
body.write(rng.bytes(16_385))
1161+
body.rewind
1162+
1163+
payload = []
1164+
IO.copy_stream(body, dst_class.new{payload << it})
1165+
body.rewind
1166+
assert_equal(body.read, payload.join, bug21131)
1167+
ensure
1168+
body&.close
1169+
end
1170+
end
1171+
11441172
def test_copy_stream_write_in_binmode
11451173
bug8767 = '[ruby-core:56518] [Bug #8767]'
11461174
mkcdtmpdir {

0 commit comments

Comments
 (0)
0