ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
@ 2025-02-13  0:11 chucke (Tiago Cardoso) via ruby-core
  2025-02-18  2:25 ` [ruby-core:121098] " jeremyevans0 (Jeremy Evans) via ruby-core
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: chucke (Tiago Cardoso) via ruby-core @ 2025-02-13  0:11 UTC (permalink / raw)
  To: ruby-core; +Cc: chucke (Tiago Cardoso)

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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:121098] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
  2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
@ 2025-02-18  2:25 ` jeremyevans0 (Jeremy Evans) via ruby-core
  2025-02-19 22:40 ` [ruby-core:121129] " chucke (Tiago Cardoso) via ruby-core
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: jeremyevans0 (Jeremy Evans) via ruby-core @ 2025-02-18  2:25 UTC (permalink / raw)
  To: ruby-core; +Cc: jeremyevans0 (Jeremy Evans)

Issue #21131 has been updated by jeremyevans0 (Jeremy Evans).

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

----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131#change-112018

* Author: chucke (Tiago Cardoso)
* Status: Open
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:121129] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
  2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
  2025-02-18  2:25 ` [ruby-core:121098] " jeremyevans0 (Jeremy Evans) via ruby-core
@ 2025-02-19 22:40 ` chucke (Tiago Cardoso) via ruby-core
  2025-03-03 23:07 ` [ruby-core:121228] " k0kubun (Takashi Kokubun) via ruby-core
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: chucke (Tiago Cardoso) via ruby-core @ 2025-02-19 22:40 UTC (permalink / raw)
  To: ruby-core; +Cc: chucke (Tiago Cardoso)

Issue #21131 has been updated by chucke (Tiago Cardoso).


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

----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131#change-112053

* Author: chucke (Tiago Cardoso)
* Status: Closed
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:121228] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
  2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
  2025-02-18  2:25 ` [ruby-core:121098] " jeremyevans0 (Jeremy Evans) via ruby-core
  2025-02-19 22:40 ` [ruby-core:121129] " chucke (Tiago Cardoso) via ruby-core
@ 2025-03-03 23:07 ` k0kubun (Takashi Kokubun) via ruby-core
  2025-03-13  4:22 ` [ruby-core:121314] " hsbt (Hiroshi SHIBATA) via ruby-core
  2025-03-16 12:22 ` [ruby-core:121384] [Ruby " nagachika (Tomoyuki Chikanaga) via ruby-core
  4 siblings, 0 replies; 6+ messages in thread
From: k0kubun (Takashi Kokubun) via ruby-core @ 2025-03-03 23:07 UTC (permalink / raw)
  To: ruby-core; +Cc: k0kubun (Takashi Kokubun)

Issue #21131 has been updated by k0kubun (Takashi Kokubun).

Backport changed from 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED to 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE

ruby_3_4 commit:eb8ee7c189d051e656f781ce2775ede1157edd6a.

----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131#change-112176

* Author: chucke (Tiago Cardoso)
* Status: Closed
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:121314] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped
  2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
                   ` (2 preceding siblings ...)
  2025-03-03 23:07 ` [ruby-core:121228] " k0kubun (Takashi Kokubun) via ruby-core
@ 2025-03-13  4:22 ` hsbt (Hiroshi SHIBATA) via ruby-core
  2025-03-16 12:22 ` [ruby-core:121384] [Ruby " nagachika (Tomoyuki Chikanaga) via ruby-core
  4 siblings, 0 replies; 6+ messages in thread
From: hsbt (Hiroshi SHIBATA) via ruby-core @ 2025-03-13  4:22 UTC (permalink / raw)
  To: ruby-core; +Cc: hsbt (Hiroshi SHIBATA)

Issue #21131 has been updated by hsbt (Hiroshi SHIBATA).

Backport changed from 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE to 3.1: REQUIRED, 3.2: DONE, 3.3: REQUIRED, 3.4: DONE

ruby_3_2 commit:4e9100b9974df197e569298655d37b8a2fadcfa5 merged revision(s) commit:f423f6e10c0c226dfed98e7cb7a5d489191dfa35.

----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131#change-112278

* Author: chucke (Tiago Cardoso)
* Status: Closed
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: REQUIRED, 3.2: DONE, 3.3: REQUIRED, 3.4: DONE
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:121384] [Ruby Bug#21131] IO.copy_stream: yielded string changes value when duped
  2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
                   ` (3 preceding siblings ...)
  2025-03-13  4:22 ` [ruby-core:121314] " hsbt (Hiroshi SHIBATA) via ruby-core
@ 2025-03-16 12:22 ` nagachika (Tomoyuki Chikanaga) via ruby-core
  4 siblings, 0 replies; 6+ messages in thread
From: nagachika (Tomoyuki Chikanaga) via ruby-core @ 2025-03-16 12:22 UTC (permalink / raw)
  To: ruby-core; +Cc: nagachika (Tomoyuki Chikanaga)

Issue #21131 has been updated by nagachika (Tomoyuki Chikanaga).

Backport changed from 3.1: REQUIRED, 3.2: DONE, 3.3: REQUIRED, 3.4: DONE to 3.1: REQUIRED, 3.2: DONE, 3.3: DONE, 3.4: DONE

ruby_3_3 commit:f85e5e01bafeca387e833b9d79cab43a8b22aa3d merged revision(s) commit:f423f6e10c0c226dfed98e7cb7a5d489191dfa35.

----------------------------------------
Bug #21131: IO.copy_stream: yielded string changes value when duped
https://bugs.ruby-lang.org/issues/21131#change-112355

* Author: chucke (Tiago Cardoso)
* Status: Closed
* ruby -v: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x86_64-darwin23]
* Backport: 3.1: REQUIRED, 3.2: DONE, 3.3: DONE, 3.4: DONE
----------------------------------------
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/

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-03-16 12:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-13  0:11 [ruby-core:120961] [Ruby master Bug#21131] IO.copy_stream: yielded string changes value when duped chucke (Tiago Cardoso) via ruby-core
2025-02-18  2:25 ` [ruby-core:121098] " jeremyevans0 (Jeremy Evans) via ruby-core
2025-02-19 22:40 ` [ruby-core:121129] " chucke (Tiago Cardoso) via ruby-core
2025-03-03 23:07 ` [ruby-core:121228] " k0kubun (Takashi Kokubun) via ruby-core
2025-03-13  4:22 ` [ruby-core:121314] " hsbt (Hiroshi SHIBATA) via ruby-core
2025-03-16 12:22 ` [ruby-core:121384] [Ruby " nagachika (Tomoyuki Chikanaga) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).