@@ -497,20 +497,27 @@ def _peek(self, num=1, full=True):
497
497
# off by 4 bytes to try to point the user at the right spot.
498
498
self ._error ("Invalid length field %d" % num , - 4 )
499
499
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 )
514
521
515
522
def _error (self , message , offset = 0 ):
516
523
oldpos = self ._stream .tell ()
0 commit comments