diff mercurial/statichttprepo.py @ 51899:e26a08563223

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.
author Matt Harbison <matt_harbison@yahoo.com>
date Wed, 25 Sep 2024 01:12:39 -0400
parents 159854151f0f
children 77a9c7d8a7ba
line wrap: on
line diff
--- 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