Skip to content

Commit be46ba2

Browse files
Fix IO::Delimited reading into limited slice with peek (#14772)
1 parent 53c4991 commit be46ba2

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

spec/std/io/delimited_spec.cr

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ describe "IO::Delimited" do
259259
io.gets_to_end.should eq("hello")
260260
end
261261

262+
it "handles the case of peek matching first byte, not having enough room, but later not matching (limted slice)" do
263+
# not a delimiter
264+
# ---
265+
io = MemoryIOWithFixedPeek.new("abcdefgwijkfghhello")
266+
# ------- ---
267+
# peek delimiter
268+
io.peek_size = 7
269+
delimited = IO::Delimited.new(io, read_delimiter: "fgh")
270+
271+
delimited.peek.should eq("abcde".to_slice)
272+
delimited.read_string(6).should eq "abcdef"
273+
delimited.read_string(5).should eq("gwijk")
274+
delimited.gets_to_end.should eq("")
275+
io.gets_to_end.should eq("hello")
276+
end
277+
262278
it "handles the case of peek matching first byte, not having enough room, later only partially matching" do
263279
# delimiter
264280
# ------------

src/io/delimited.cr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,13 @@ class IO::Delimited < IO
111111
next_index = @active_delimiter_buffer.index(first_byte, 1)
112112

113113
# We read up to that new match, if any, or the entire buffer
114-
read_bytes = next_index || @active_delimiter_buffer.size
114+
read_bytes = Math.min(next_index || @active_delimiter_buffer.size, slice.size)
115115

116116
slice.copy_from(@active_delimiter_buffer[0, read_bytes])
117117
slice += read_bytes
118118
@active_delimiter_buffer += read_bytes
119+
120+
return read_bytes if slice.empty?
119121
return read_bytes + read_internal(slice)
120122
end
121123
end

0 commit comments

Comments
 (0)