# HG changeset patch # User Matt Harbison # Date 1727241159 14400 # Node ID e26a085632234668ef3812b1abb7dc1953fd02fb # Parent 159854151f0fc8cb7305c02a3b4f24b2e3aa9bf9 statichttprepo: fix `httprangereader.read()` for py3 It looks like there were a bunch of problems, not all of them py3 related: 1) The signature of BinaryIO.read() is -1, not None 2) The `end` variable can't be bytes and interpolate into str with "%s" 3) The `end` variable can't be an int and interpolate into str with "%s" 4) The result slicing could be out of bounds if more is requested than returned I guess if somebody would have called `read(-1)` (either directly or because a wrapper defaults to that), it wouldn't have been handled correctly. The fact that it is a valid value meaning to read everything requires some additional changes later in the method around when it slices the byte string that was read, but that seems to have already been broken. diff -r 159854151f0f -r e26a08563223 mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py Wed Sep 25 00:52:44 2024 -0400 +++ b/mercurial/statichttprepo.py Wed Sep 25 01:12:39 2024 -0400 @@ -52,11 +52,14 @@ def seek(self, pos): self.pos = pos - def read(self, bytes=None): + def read(self, bytes: int = -1): req = urlreq.request(pycompat.strurl(self.url)) - end = b'' - if bytes: - end = self.pos + bytes - 1 + end = '' + + if bytes == 0: + return b'' + elif bytes > 0: + end = "%d" % (self.pos + bytes - 1) if self.pos or end: req.add_header('Range', 'bytes=%d-%s' % (self.pos, end)) @@ -76,11 +79,13 @@ if code == 200: # HTTPRangeHandler does nothing if remote does not support # Range headers and returns the full entity. Let's slice it. - if bytes: + if bytes > 0 and (self.pos + bytes) < len(data): data = data[self.pos : self.pos + bytes] + elif self.pos < len(data): + data = data[self.pos :] else: - data = data[self.pos :] - elif bytes: + data = b'' + elif 0 < bytes < len(data): data = data[:bytes] self.pos += len(data) return data