[ruby/net-protocol] Undo BufferedIO#rbuf_consume_all_shareable! optimization

This optimization is unsafe because `dest` is allowed to be a custom
object responding to `<<` (e.g. a block wrapped in `ReadAdapter`).

So the receiver can hold onto the passed buffer for as long as it wants.

If it was guaranteed that `ReadAdapter` was the only possible receiver
we could dup the buffer there for mutation safety, but I'm not certain
it's the case so I'd rather err on the safe side.

Ref: https://github.com/shrinerb/shrine/issues/610

https://github.com/ruby/net-protocol/commit/7efa16d55d
This commit is contained in:
Jean Boussier 2022-12-07 16:37:09 +01:00 committed by git
parent a57a3154d3
commit 8547f61daf

View File

@ -156,7 +156,7 @@ module Net # :nodoc:
read_bytes = 0
begin
while read_bytes + rbuf_size < len
if s = rbuf_consume_all_shareable!
if s = rbuf_consume_all
read_bytes += s.bytesize
dest << s
end
@ -177,7 +177,7 @@ module Net # :nodoc:
read_bytes = 0
begin
while true
if s = rbuf_consume_all_shareable!
if s = rbuf_consume_all
read_bytes += s.bytesize
dest << s
end
@ -249,18 +249,8 @@ module Net # :nodoc:
@rbuf.bytesize - @rbuf_offset
end
# Warning: this method may share the buffer to avoid
# copying. The caller must no longer use the returned
# string once rbuf_fill has been called again
def rbuf_consume_all_shareable!
@rbuf_empty = true
buf = if @rbuf_offset == 0
@rbuf
else
@rbuf.byteslice(@rbuf_offset..-1)
end
@rbuf_offset = @rbuf.bytesize
buf
def rbuf_consume_all
rbuf_consume if rbuf_size > 0
end
def rbuf_consume(len = nil)