Project

General

Profile

Actions

Bug #21131

closed

IO.copy_stream: yielded string changes value when duped

Added by chucke (Tiago Cardoso) 10 days ago. Updated 3 days ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
[ruby-core:120961]

Description

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).

Updated by jeremyevans0 (Jeremy Evans) 4 days ago

  • Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED

Thank you for the report. This is definitely a bug. My testing shows it affects all versions of Ruby, at least back to 1.9.3. I submitted a PR to fix this issue: https://github.com/ruby/ruby/pull/12771

Actions #2

Updated by jeremyevans (Jeremy Evans) 3 days ago

  • Status changed from Open to Closed

Applied in changeset git|f423f6e10c0c226dfed98e7cb7a5d489191dfa35.


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]

Updated by chucke (Tiago Cardoso) 3 days ago

Thank you jeremy! Was planning to take a stab at it to see if I could do it, but thankful that you jumped in.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0