From 8f9da5382bc03c30346c4078ffbbde442de423c6 Mon Sep 17 00:00:00 2001 From: icanhasmath Date: Wed, 28 Oct 2026 17:26:58 -0500 Subject: [PATCH 1/2] gh-151981: Don't pass a huge block count to xrange() in tarfile._Stream.seek The CVE-2026-11972 backport (337d3ddd1d2) stops _Stream.seek() at EOF, but it kept the loop as `for i in xrange(blocks)`. On 2.7, xrange() takes a C long, which is 32 bits on Windows, so a header declaring a size near 2**64 (blocks ~ 2**51) raises OverflowError before the EOF check runs, and the hostile archive escapes as an unexpected exception type instead of ReadError. test_getmembers_big_size fails in all three stream modes on the Windows x64 build of 2.7.18.16rc1; it passes on Linux, where C long is 64 bits. Count blocks down in a while loop instead. Co-Authored-By: Claude Opus 5.5 --- Lib/tarfile.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 223b573f45122c3..49460167b388e99 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -555,10 +555,13 @@ def seek(self, pos=0): """ if pos - self.pos >= 0: blocks, remainder = divmod(pos - self.pos, self.bufsize) - for i in xrange(blocks): + # Not xrange(): it takes a C long, which is 32 bits on Windows, + # and a header can declare a size that makes blocks huge. + while blocks > 0: data = self.read(self.bufsize) if not data: break + blocks -= 1 self.read(remainder) else: raise StreamError("seeking backwards is not allowed") From 2f8d0d474e47ca9d3ce3988fc8fcc811fceb4cb5 Mon Sep 17 00:00:00 2001 From: icanhasmath Date: Wed, 28 Oct 2026 17:26:58 -0500 Subject: [PATCH 2/2] test_ssl: run the CVE-2026-19445 SNI tests where socketpair() is missing sni_handshake_released_context() built its connection with socket.socketpair(), which 2.7 only has on POSIX, so both test_sni_callback_context_released_* tests errored on Windows and the CVE-2026-19445 fix (784022998c9) went unexercised there. Fall back to a loopback TCP pair. Both tests pass on the Windows x64 2.7.18.16rc1 runtime with this change, and test_ssl is unchanged on Linux. Co-Authored-By: Claude Opus 5.5 --- Lib/test/test_ssl.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 8c689f7aaa32768..c105145ef624b7f 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -3318,7 +3318,16 @@ def make_server(sock): sock, server_side=True, do_handshake_on_connect=False) return server, weakref.ref(dispatch_ctx) - s1, s2 = [socket.socket(_sock=s) for s in socket.socketpair()] + if hasattr(socket, "socketpair"): + s1, s2 = [socket.socket(_sock=s) for s in socket.socketpair()] + else: + # 2.7 has no socketpair() on Windows; use a loopback TCP pair. + with closing(socket.socket()) as listener: + listener.bind((HOST, 0)) + listener.listen(1) + s2 = socket.socket() + s2.connect(listener.getsockname()) + s1 = listener.accept()[0] self.addCleanup(s1.close) self.addCleanup(s2.close) server, dispatch_ref = make_server(s1)