@@ -542,26 +542,43 @@ def _read(self, size):
542542 c = 0
543543 t = []
544544 while c < size :
545- # Skip underlying buffer to avoid unaligned double buffering.
546- if self . buf :
547- buf = self . buf
548- self .buf = b""
549- elif self . comptype != "gz" and not self .cmp . needs_input :
550- buf = b""
551- else :
552- buf = self .fileobj .read (self .bufsize )
553- if not buf :
554- break
555- try :
556- buf = self . cmp . decompress ( buf , size - c )
557- if self .comptype == "gz" :
545+ if self . comptype == "gz" :
546+ # zlib interface is different than others.
547+ # It returns data in unconsumed_tail.
548+ if self .buf :
549+ cbuf = self .buf
550+ self . buf = b""
551+ else :
552+ cbuf = self .fileobj .read (self .bufsize )
553+ if not cbuf :
554+ break
555+
556+ try :
557+ dbuf = self .cmp . decompress ( cbuf , size - c )
558558 self .buf = self .cmp .unconsumed_tail
559- except self .exception as e :
560- raise ReadError ("invalid compressed data" ) from e
561- t .append (buf )
562- c += len (buf )
559+ except self .exception as e :
560+ raise ReadError ("invalid compressed data" ) from e
561+ else :
562+ # Other decompressors have needs_input.
563+ # decompress() can buffer data internally.
564+ if self .cmp .needs_input :
565+ cbuf = self .fileobj .read (self .bufsize )
566+ if not cbuf :
567+ break
568+ else :
569+ cbuf = b""
570+
571+ try :
572+ dbuf = self .cmp .decompress (cbuf , size - c )
573+ except self .exception as e :
574+ raise ReadError ("invalid compressed data" ) from e
575+
576+ t .append (dbuf )
577+ c += len (dbuf )
578+
563579 t = b"" .join (t )
564580 if len (t ) > size :
581+ # This would only happen if decompress() has a bug.
565582 raise ReadError ("decompress() returned too much data" )
566583 return t
567584
0 commit comments