Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/yaml/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ def peek(self, index=0):
return self.buffer[self.pointer+index]
except IndexError:
self.update(index+1)
return self.buffer[self.pointer+index]
if self.pointer+index < len(self.buffer):
return self.buffer[self.pointer+index]
return '\0'

def prefix(self, length=1):
if self.pointer+length >= len(self.buffer):
Expand Down
56 changes: 56 additions & 0 deletions tests/test_reader_peek.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import io

import yaml
import yaml.reader


class TestReaderPeekBeyondBuffer:
"""Tests for Reader.peek() when index exceeds available data.

Regression test for https://github.com/yaml/pyyaml/issues/904
"""

def test_peek_beyond_end_returns_null(self):
"""peek() past end of a string stream should return '\\0', not raise IndexError."""
reader = yaml.reader.Reader('abc')
assert reader.peek(4) == '\0'

def test_peek_at_null_terminator(self):
"""peek() at the exact position of the null terminator should return '\\0'."""
reader = yaml.reader.Reader('abc')
# buffer is 'abc\0', so index 3 is the '\0'
assert reader.peek(3) == '\0'

def test_peek_far_beyond_end(self):
"""peek() with a very large index should return '\\0'."""
reader = yaml.reader.Reader('abc')
assert reader.peek(100) == '\0'

def test_peek_within_range(self):
"""peek() within range should still return the correct character."""
reader = yaml.reader.Reader('abc')
assert reader.peek(0) == 'a'
assert reader.peek(1) == 'b'
assert reader.peek(2) == 'c'

def test_peek_empty_string(self):
"""peek() on an empty string should return '\\0'."""
reader = yaml.reader.Reader('')
assert reader.peek(0) == '\0'
assert reader.peek(1) == '\0'

def test_peek_beyond_end_bytes(self):
"""peek() past end of a bytes stream should return '\\0'."""
reader = yaml.reader.Reader(b'abc')
assert reader.peek(4) == '\0'

def test_peek_beyond_end_file_stream(self):
"""peek() past end of a file-like stream should return '\\0'."""
reader = yaml.reader.Reader(io.StringIO('abc'))
assert reader.peek(4) == '\0'

def test_loader_peek_beyond_end(self):
"""Original reproducer from issue #904."""
obj = yaml.loader.Loader('abc')
ret = obj.peek(4)
assert ret == '\0'