Skip to content

Commit 2a19caf

Browse files
Merge branch 'main' into sl-19314
2 parents ba99d6c + 438e41d commit 2a19caf

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

llsd/base.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -497,20 +497,27 @@ def _peek(self, num=1, full=True):
497497
# off by 4 bytes to try to point the user at the right spot.
498498
self._error("Invalid length field %d" % num, -4)
499499

500-
got = self._stream.peek(num)
501-
if full and len(got) < num:
502-
# Going right to this error is a little iffy:
503-
# BufferedReader.peek() does not promise to return the requested
504-
# length, but does not clarify the conditions under which it
505-
# returns fewer bytes. If this is an actual problem, we could loop
506-
# until we have the requested length or EOF -- but the loop must
507-
# explicitly seek() past already-peeked data, then reset after.
508-
# https://docs.python.org/3/library/io.html#io.BufferedReader.peek
509-
self._error("Trying to peek past end of stream")
510-
511-
# Interestingly, peek() can also return MORE than requested -- but for
512-
# our purposes (e.g. ord(peek(1))) it's important to constrain it.
513-
return got[:num]
500+
# Instead of using self._stream.peek() at all, use read(num) and reset
501+
# the read pointer. BufferedReader.peek() does not promise to return
502+
# the requested length, but does not clarify the conditions under
503+
# which it returns fewer bytes.
504+
# https://docs.python.org/3/library/io.html#io.BufferedReader.peek
505+
# In practice, we've seen it fail with an input file up over 100Kb:
506+
# peek() returns only part of what we requested, but because we also
507+
# passed full=False (see LLSDNotationParser._get_re()), we didn't
508+
# notice and the parse failed looking for a map delimiter halfway
509+
# through a large decimal integer. read(num), on the other hand,
510+
# promises to return num bytes until actual EOF.
511+
oldpos = self._stream.tell()
512+
try:
513+
got = self._stream.read(num)
514+
if full and len(got) < num:
515+
self._error("Trying to peek past end of stream")
516+
517+
return got
518+
519+
finally:
520+
self._stream.seek(oldpos)
514521

515522
def _error(self, message, offset=0):
516523
oldpos = self._stream.tell()

0 commit comments

Comments
 (0)