From 7efa16d55d5cedae5871ce59b9c285f7f390b957 Mon Sep 17 00:00:00 2001 From: Jean Boussier <jean.boussier@gmail.com> Date: Wed, 7 Dec 2022 16:37:09 +0100 Subject: [PATCH] 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 --- lib/net/protocol.rb | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index aba6557..728cc19 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -157,7 +157,7 @@ def read(len, dest = ''.b, ignore_eof = false) 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 @@ -178,7 +178,7 @@ def read_all(dest = ''.b) read_bytes = 0 begin while true - if s = rbuf_consume_all_shareable! + if s = rbuf_consume_all read_bytes += s.bytesize dest << s end @@ -250,18 +250,8 @@ def rbuf_size @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)