clonebundle-digest: add recursion guards for Python 3.8
authorJoerg Sonnenberger <joerg@bec.de>
Fri, 11 Oct 2024 14:37:59 +0200
changeset 51992 71658f79758a
parent 51991 f0bee30af890
child 51993 daeb85ebee48
clonebundle-digest: add recursion guards for Python 3.8 For Python 3.8 and 3.9, the read/readinto pair can recurse, so make sure the data is only hashed once.
mercurial/url.py
--- a/mercurial/url.py	Tue Oct 08 01:06:57 2024 -0400
+++ b/mercurial/url.py	Fri Oct 11 14:37:59 2024 +0200
@@ -538,18 +538,27 @@
                         )
 
             def read(self, amt=None):
+                self._digest_recursion_level += 1
                 data = super().read(amt)
-                self._digest_input(data)
+                self._digest_recursion_level -= 1
+                if self._digest_recursion_level == 0:
+                    self._digest_input(data)
                 return data
 
             def readline(self):
+                self._digest_recursion_level += 1
                 data = super().readline()
-                self._digest_input(data)
+                self._digest_recursion_level -= 1
+                if self._digest_recursion_level == 0:
+                    self._digest_input(data)
                 return data
 
             def readinto(self, dest):
+                self._digest_recursion_level += 1
                 got = super().readinto(dest)
-                self._digest_input(dest[:got])
+                self._digest_recursion_level -= 1
+                if self._digest_recursion_level == 0:
+                    self._digest_input(dest[:got])
                 return got
 
             def _close_conn(self):
@@ -560,6 +569,8 @@
         response._digest = self._digest
         response._digest_consumed = 0
         response._hasher = self._hasher.copy()
+        # Python 3.8 / 3.9 recurses internally between read/readinto.
+        response._digest_recursion_level = 0
         response._digest_finished = False
         return response