From 75363efa74a6f9e3293f933f64d4867de2881d6e0b2aa969a0890a7e736e0b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Cepl?= Date: Fri, 6 Mar 2026 20:38:27 +0100 Subject: [PATCH] Update to 3.12.13: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Python 3.12.13 final - Release date: 2026-03-03 - Security - gh-144125: BytesGenerator will now refuse to serialize (write) headers that are unsafely folded or delimited; see verify_generated_headers. (Contributed by Bas Bloemsaat and Petr Viktorin in gh-121650). - gh-143935: Fixed a bug in the folding of comments when flattening an email message using a modern email policy. Comments consisting of a very long sequence of non-foldable characters could trigger a forced line wrap that omitted the required leading space on the continuation line, causing the remainder of the comment to be interpreted as a new header field. This enabled header injection with carefully crafted inputs (bsc#1257029 CVE-2025-11468). - gh-143925: Reject control characters in data: URL media types (bsc#1257046, CVE-2025-15282). - gh-143919: Reject control characters in http.cookies.Morsel fields and values (bsc#1257031, CVE-2026-0672). - gh-143916: Reject C0 control characters within wsgiref.headers.Headers fields, values, and parameters (bsc#1257042, CVE-2026-0865). - gh-142145: Remove quadratic behavior in xml.minidom node ID cache clearing. In order to do this without breaking existing users, we also add the ownerDocument attribute to xml.dom.minidom elements and attributes created by directly instantiating the Element or Attr class. Note that this way of creating nodes is not supported; creator functions like xml.dom.Document.documentElement() should be used instead (bsc#1254997, CVE-2025-12084). - gh-137836: Add support of the “plaintext” element, RAWTEXT elements “xmp”, “iframe”, “noembed” and “noframes”, and optionally RAWTEXT element “noscript” in html.parser.HTMLParser. - gh-136063: email.message: ensure linear complexity for legacy HTTP parameters parsing. Patch by Bénédikt Tran. - gh-136065: Fix quadratic complexity in os.path.expandvars() (bsc#1252974, CVE-2025-6075). - gh-119451: Fix a potential memory denial of service in the http.client module. When connecting to a malicious server, it could cause an arbitrary amount of memory to be allocated. This could have led to symptoms including a MemoryError, swapping, out of memory (OOM) killed processes or containers, or even system crashes (CVE-2025-13836, bsc#1254400). - gh-119452: Fix a potential memory denial of service in the http.server module. When a malicious user is connected to the CGI server on Windows, it could cause an arbitrary amount of memory to be allocated. This could have led to symptoms including a MemoryError, swapping, out of memory (OOM) killed processes or containers, or even system crashes. - gh-119342: Fix a potential memory denial of service in the plistlib module. When reading a Plist file received from untrusted source, it could cause an arbitrary amount of memory to be allocated. This could have led to symptoms including a MemoryError, swapping, out of memory (OOM) killed processes or containers, or even system crashes (bsc#1254401, CVE-2025-13837). - Library - gh-144833: Fixed a use-after-free in ssl when SSL_new() returns NULL in newPySSLSocket(). The error was reported via a dangling pointer after the object had already been freed. - gh-144363: Update bundled libexpat to 2.7.4 - gh-90949: Add SetAllocTrackerActivationThreshold() and SetAllocTrackerMaximumAmplification() to xmlparser objects to prevent use of disproportional amounts of dynamic memory from within an Expat parser. Patch by Bénédikt Tran. Remove upstreamed patches: - CVE-2025-11468-email-hdr-fold-comment.patch - CVE-2025-12084-minidom-quad-search.patch - CVE-2025-13836-http-resp-cont-len.patch - CVE-2025-13837-plistlib-mailicious-length.patch - CVE-2025-6075-expandvars-perf-degrad.patch - CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch - CVE-2026-0865-wsgiref-ctrl-chars.patch - CVE-2025-15282-urllib-ctrl-chars.patch --- CVE-2025-11468-email-hdr-fold-comment.patch | 108 ----- CVE-2025-12084-minidom-quad-search.patch | 94 ----- CVE-2025-12781-b64decode-alt-chars.patch | 22 +- CVE-2025-13836-http-resp-cont-len.patch | 154 ------- ...025-13837-plistlib-mailicious-length.patch | 159 -------- CVE-2025-15282-urllib-ctrl-chars.patch | 64 --- CVE-2025-15366-imap-ctrl-chars.patch | 10 +- CVE-2025-15367-poplib-ctrl-chars.patch | 16 +- CVE-2025-6075-expandvars-perf-degrad.patch | 382 ------------------ ...6-0672-http-hdr-inject-cookie-Morsel.patch | 183 --------- CVE-2026-0865-wsgiref-ctrl-chars.patch | 96 ----- Python-3.12.12.tar.xz | 3 - Python-3.12.12.tar.xz.asc | 18 - Python-3.12.12.tar.xz.sigstore | 1 - Python-3.12.13.tar.xz | 3 + Python-3.12.13.tar.xz.asc | 18 + Python-3.12.13.tar.xz.sigstore | 1 + fix_configure_rst.patch | 14 +- pass-test_write_read_limited_history.patch | 10 +- python312.changes | 83 ++++ python312.spec | 2 +- 21 files changed, 144 insertions(+), 1297 deletions(-) delete mode 100644 CVE-2025-11468-email-hdr-fold-comment.patch delete mode 100644 CVE-2025-12084-minidom-quad-search.patch delete mode 100644 CVE-2025-13836-http-resp-cont-len.patch delete mode 100644 CVE-2025-13837-plistlib-mailicious-length.patch delete mode 100644 CVE-2025-15282-urllib-ctrl-chars.patch delete mode 100644 CVE-2025-6075-expandvars-perf-degrad.patch delete mode 100644 CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch delete mode 100644 CVE-2026-0865-wsgiref-ctrl-chars.patch delete mode 100644 Python-3.12.12.tar.xz delete mode 100644 Python-3.12.12.tar.xz.asc delete mode 100644 Python-3.12.12.tar.xz.sigstore create mode 100644 Python-3.12.13.tar.xz create mode 100644 Python-3.12.13.tar.xz.asc create mode 100644 Python-3.12.13.tar.xz.sigstore diff --git a/CVE-2025-11468-email-hdr-fold-comment.patch b/CVE-2025-11468-email-hdr-fold-comment.patch deleted file mode 100644 index 5dbcb4f..0000000 --- a/CVE-2025-11468-email-hdr-fold-comment.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 3900a2cb7d8321629717b8483179263a968bf552 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Mon, 19 Jan 2026 06:38:22 -0600 -Subject: [PATCH] gh-143935: Email preserve parens when folding comments - (GH-143936) - -Fix a bug in the folding of comments when flattening an email message -using a modern email policy. Comments consisting of a very long sequence of -non-foldable characters could trigger a forced line wrap that omitted the -required leading space on the continuation line, causing the remainder of -the comment to be interpreted as a new header field. This enabled header -injection with carefully crafted inputs. -(cherry picked from commit 17d1490aa97bd6b98a42b1a9b324ead84e7fd8a2) - -Co-authored-by: Seth Michael Larson -Co-authored-by: Denis Ledoux ---- - Lib/email/_header_value_parser.py | 15 ++++++ - Lib/test/test_email/test__header_value_parser.py | 23 ++++++++++ - Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst | 6 ++ - 3 files changed, 43 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst - -Index: Python-3.12.12/Lib/email/_header_value_parser.py -=================================================================== ---- Python-3.12.12.orig/Lib/email/_header_value_parser.py 2026-02-06 00:08:35.667684507 +0100 -+++ Python-3.12.12/Lib/email/_header_value_parser.py 2026-02-06 00:08:40.746286971 +0100 -@@ -101,6 +101,12 @@ - return str(value).replace('\\', '\\\\').replace('"', '\\"') - - -+def make_parenthesis_pairs(value): -+ """Escape parenthesis and backslash for use within a comment.""" -+ return str(value).replace('\\', '\\\\') \ -+ .replace('(', '\\(').replace(')', '\\)') -+ -+ - def quote_string(value): - escaped = make_quoted_pairs(value) - return f'"{escaped}"' -@@ -933,7 +939,7 @@ - return ' ' - - def startswith_fws(self): -- return True -+ return self and self[0] in WSP - - - class ValueTerminal(Terminal): -@@ -2922,6 +2928,13 @@ - [ValueTerminal(make_quoted_pairs(p), 'ptext') - for p in newparts] + - [ValueTerminal('"', 'ptext')]) -+ if part.token_type == 'comment': -+ newparts = ( -+ [ValueTerminal('(', 'ptext')] + -+ [ValueTerminal(make_parenthesis_pairs(p), 'ptext') -+ if p.token_type == 'ptext' else p -+ for p in newparts] + -+ [ValueTerminal(')', 'ptext')]) - if not part.as_ew_allowed: - wrap_as_ew_blocked += 1 - newparts.append(end_ew_not_allowed) -Index: Python-3.12.12/Lib/test/test_email/test__header_value_parser.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_email/test__header_value_parser.py 2026-02-06 00:08:37.343959625 +0100 -+++ Python-3.12.12/Lib/test/test_email/test__header_value_parser.py 2026-02-06 00:08:40.747102748 +0100 -@@ -3141,6 +3141,29 @@ - with self.subTest(to=to): - self._test(parser.get_address_list(to)[0], folded, policy=policy) - -+ def test_address_list_with_long_unwrapable_comment(self): -+ policy = self.policy.clone(max_line_length=40) -+ cases = [ -+ # (to, folded) -+ ('(loremipsumdolorsitametconsecteturadipi)', -+ '(loremipsumdolorsitametconsecteturadipi)\n'), -+ ('(loremipsumdolorsitametconsecteturadipi)', -+ '(loremipsumdolorsitametconsecteturadipi)\n'), -+ ('(loremipsum dolorsitametconsecteturadipi)', -+ '(loremipsum dolorsitametconsecteturadipi)\n'), -+ ('(loremipsum dolorsitametconsecteturadipi)', -+ '(loremipsum\n dolorsitametconsecteturadipi)\n'), -+ ('(Escaped \\( \\) chars \\\\ in comments stay escaped)', -+ '(Escaped \\( \\) chars \\\\ in comments stay\n escaped)\n'), -+ ('((loremipsum)(loremipsum)(loremipsum)(loremipsum))', -+ '((loremipsum)(loremipsum)(loremipsum)(loremipsum))\n'), -+ ('((loremipsum)(loremipsum)(loremipsum) (loremipsum))', -+ '((loremipsum)(loremipsum)(loremipsum)\n (loremipsum))\n'), -+ ] -+ for (to, folded) in cases: -+ with self.subTest(to=to): -+ self._test(parser.get_address_list(to)[0], folded, policy=policy) -+ - # XXX Need tests with comments on various sides of a unicode token, - # and with unicode tokens in the comments. Spaces inside the quotes - # currently don't do the right thing. -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst 2026-02-06 00:08:40.747576711 +0100 -@@ -0,0 +1,6 @@ -+Fixed a bug in the folding of comments when flattening an email message -+using a modern email policy. Comments consisting of a very long sequence of -+non-foldable characters could trigger a forced line wrap that omitted the -+required leading space on the continuation line, causing the remainder of -+the comment to be interpreted as a new header field. This enabled header -+injection with carefully crafted inputs. diff --git a/CVE-2025-12084-minidom-quad-search.patch b/CVE-2025-12084-minidom-quad-search.patch deleted file mode 100644 index b4c8dd7..0000000 --- a/CVE-2025-12084-minidom-quad-search.patch +++ /dev/null @@ -1,94 +0,0 @@ -From df996ce4b9860f8d0c391d876ffe6d0143132a81 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Wed, 3 Dec 2025 01:16:37 -0600 -Subject: [PATCH] gh-142145: Remove quadratic behavior in node ID cache - clearing (GH-142146) - -* Remove quadratic behavior in node ID cache clearing - -Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com> - -* Add news fragment - ---------- -(cherry picked from commit 08d8e18ad81cd45bc4a27d6da478b51ea49486e4) - -Co-authored-by: Seth Michael Larson -Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com> ---- - Lib/test/test_minidom.py | 18 ++++++++++++++++++ - Lib/xml/dom/minidom.py | 9 +-------- - ...5-12-01-09-36-45.gh-issue-142145.tcAUhg.rst | 1 + - 3 files changed, 20 insertions(+), 8 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst - -diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py -index 699265ccadc7f9..a83cb88ef9be79 100644 ---- a/Lib/test/test_minidom.py -+++ b/Lib/test/test_minidom.py -@@ -2,6 +2,7 @@ - - import copy - import pickle -+import time - import io - from test import support - import unittest -@@ -176,6 +177,23 @@ def testAppendChild(self): - self.confirm(dom.documentElement.childNodes[-1].data == "Hello") - dom.unlink() - -+ def testAppendChildNoQuadraticComplexity(self): -+ impl = getDOMImplementation() -+ -+ newdoc = impl.createDocument(None, "some_tag", None) -+ top_element = newdoc.documentElement -+ children = [newdoc.createElement(f"child-{i}") for i in range(1, 2 ** 15 + 1)] -+ element = top_element -+ -+ start = time.time() -+ for child in children: -+ element.appendChild(child) -+ element = child -+ end = time.time() -+ -+ # This example used to take at least 30 seconds. -+ self.assertLess(end - start, 1) -+ - def testAppendChildFragment(self): - dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() - dom.documentElement.appendChild(frag) -diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py -index ef8a159833bbc0..83f717eeb5d043 100644 ---- a/Lib/xml/dom/minidom.py -+++ b/Lib/xml/dom/minidom.py -@@ -292,13 +292,6 @@ def _append_child(self, node): - childNodes.append(node) - node.parentNode = self - --def _in_document(node): -- # return True iff node is part of a document tree -- while node is not None: -- if node.nodeType == Node.DOCUMENT_NODE: -- return True -- node = node.parentNode -- return False - - def _write_data(writer, data): - "Writes datachars to writer." -@@ -1539,7 +1532,7 @@ def _clear_id_cache(node): - if node.nodeType == Node.DOCUMENT_NODE: - node._id_cache.clear() - node._id_search_stack = None -- elif _in_document(node): -+ elif node.ownerDocument: - node.ownerDocument._id_cache.clear() - node.ownerDocument._id_search_stack= None - -diff --git a/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst -new file mode 100644 -index 00000000000000..440bc7794c69ef ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst -@@ -0,0 +1 @@ -+Remove quadratic behavior in ``xml.minidom`` node ID cache clearing. diff --git a/CVE-2025-12781-b64decode-alt-chars.patch b/CVE-2025-12781-b64decode-alt-chars.patch index bbe241f..fde573f 100644 --- a/CVE-2025-12781-b64decode-alt-chars.patch +++ b/CVE-2025-12781-b64decode-alt-chars.patch @@ -12,10 +12,10 @@ argument of b32decode(). Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst | 5 + 4 files changed, 91 insertions(+), 14 deletions(-) -Index: Python-3.12.12/Doc/library/base64.rst +Index: Python-3.12.13/Doc/library/base64.rst =================================================================== ---- Python-3.12.12.orig/Doc/library/base64.rst 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Doc/library/base64.rst 2026-02-10 22:15:41.801235355 +0100 +--- Python-3.12.13.orig/Doc/library/base64.rst 2026-03-03 13:39:30.000000000 +0100 ++++ Python-3.12.13/Doc/library/base64.rst 2026-03-06 20:24:47.155493487 +0100 @@ -74,15 +74,20 @@ A :exc:`binascii.Error` exception is raised if *s* is incorrectly padded. @@ -52,10 +52,10 @@ Index: Python-3.12.12/Doc/library/base64.rst .. function:: b32encode(s) -Index: Python-3.12.12/Lib/base64.py +Index: Python-3.12.13/Lib/base64.py =================================================================== ---- Python-3.12.12.orig/Lib/base64.py 2026-02-10 22:15:02.534016402 +0100 -+++ Python-3.12.12/Lib/base64.py 2026-02-10 22:15:41.801591556 +0100 +--- Python-3.12.13.orig/Lib/base64.py 2026-03-06 20:21:12.189779055 +0100 ++++ Python-3.12.13/Lib/base64.py 2026-03-06 20:24:47.156270051 +0100 @@ -71,20 +71,39 @@ The result is returned as a bytes object. A binascii.Error is raised if s is incorrectly padded. @@ -121,10 +121,10 @@ Index: Python-3.12.12/Lib/base64.py -Index: Python-3.12.12/Lib/test/test_base64.py +Index: Python-3.12.13/Lib/test/test_base64.py =================================================================== ---- Python-3.12.12.orig/Lib/test/test_base64.py 2026-02-10 22:15:04.364274059 +0100 -+++ Python-3.12.12/Lib/test/test_base64.py 2026-02-10 22:17:42.445725550 +0100 +--- Python-3.12.13.orig/Lib/test/test_base64.py 2026-03-06 20:21:14.072714339 +0100 ++++ Python-3.12.13/Lib/test/test_base64.py 2026-03-06 20:24:47.156769814 +0100 @@ -232,6 +232,25 @@ b'\xd3V\xbeo\xf7\x1d') self.check_decode_type_errors(base64.urlsafe_b64decode) @@ -181,10 +181,10 @@ Index: Python-3.12.12/Lib/test/test_base64.py def test_b32encode(self): eq = self.assertEqual -Index: Python-3.12.12/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst +Index: Python-3.12.13/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst 2026-02-10 22:15:41.802353823 +0100 ++++ Python-3.12.13/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst 2026-03-06 20:24:47.157181851 +0100 @@ -0,0 +1,5 @@ +Accepting ``+`` and ``/`` characters with an alternative alphabet in +:func:`base64.b64decode` and :func:`base64.urlsafe_b64decode` is now diff --git a/CVE-2025-13836-http-resp-cont-len.patch b/CVE-2025-13836-http-resp-cont-len.patch deleted file mode 100644 index d0f96ac..0000000 --- a/CVE-2025-13836-http-resp-cont-len.patch +++ /dev/null @@ -1,154 +0,0 @@ -From b3a7998115e195c40e00cfa662bcaa899d937c05 Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -Date: Mon, 1 Dec 2025 17:26:07 +0200 -Subject: [PATCH] gh-119451: Fix a potential denial of service in http.client - (GH-119454) - -Reading the whole body of the HTTP response could cause OOM if -the Content-Length value is too large even if the server does not send -a large amount of data. Now the HTTP client reads large data by chunks, -therefore the amount of consumed memory is proportional to the amount -of sent data. -(cherry picked from commit 5a4c4a033a4a54481be6870aa1896fad732555b5) - -Co-authored-by: Serhiy Storchaka ---- - Lib/http/client.py | 28 +++- - Lib/test/test_httplib.py | 66 ++++++++++ - Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst | 5 - 3 files changed, 95 insertions(+), 4 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst - -Index: Python-3.12.12/Lib/http/client.py -=================================================================== ---- Python-3.12.12.orig/Lib/http/client.py 2025-12-18 19:10:59.442847463 +0100 -+++ Python-3.12.12/Lib/http/client.py 2025-12-18 19:11:10.279358227 +0100 -@@ -111,6 +111,11 @@ - _MAXLINE = 65536 - _MAXHEADERS = 100 - -+# Data larger than this will be read in chunks, to prevent extreme -+# overallocation. -+_MIN_READ_BUF_SIZE = 1 << 20 -+ -+ - # Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2) - # - # VCHAR = %x21-7E -@@ -639,10 +644,25 @@ - reading. If the bytes are truly not available (due to EOF), then the - IncompleteRead exception can be used to detect the problem. - """ -- data = self.fp.read(amt) -- if len(data) < amt: -- raise IncompleteRead(data, amt-len(data)) -- return data -+ cursize = min(amt, _MIN_READ_BUF_SIZE) -+ data = self.fp.read(cursize) -+ if len(data) >= amt: -+ return data -+ if len(data) < cursize: -+ raise IncompleteRead(data, amt - len(data)) -+ -+ data = io.BytesIO(data) -+ data.seek(0, 2) -+ while True: -+ # This is a geometric increase in read size (never more than -+ # doubling out the current length of data per loop iteration). -+ delta = min(cursize, amt - cursize) -+ data.write(self.fp.read(delta)) -+ if data.tell() >= amt: -+ return data.getvalue() -+ cursize += delta -+ if data.tell() < cursize: -+ raise IncompleteRead(data.getvalue(), amt - data.tell()) - - def _safe_readinto(self, b): - """Same as _safe_read, but for reading into a buffer.""" -Index: Python-3.12.12/Lib/test/test_httplib.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_httplib.py 2025-12-18 19:11:00.972941560 +0100 -+++ Python-3.12.12/Lib/test/test_httplib.py 2025-12-18 19:11:10.279958169 +0100 -@@ -1452,6 +1452,72 @@ - thread.join() - self.assertEqual(result, b"proxied data\n") - -+ def test_large_content_length(self): -+ serv = socket.create_server((HOST, 0)) -+ self.addCleanup(serv.close) -+ -+ def run_server(): -+ [conn, address] = serv.accept() -+ with conn: -+ while conn.recv(1024): -+ conn.sendall( -+ b"HTTP/1.1 200 Ok\r\n" -+ b"Content-Length: %d\r\n" -+ b"\r\n" % size) -+ conn.sendall(b'A' * (size//3)) -+ conn.sendall(b'B' * (size - size//3)) -+ -+ thread = threading.Thread(target=run_server) -+ thread.start() -+ self.addCleanup(thread.join, 1.0) -+ -+ conn = client.HTTPConnection(*serv.getsockname()) -+ try: -+ for w in range(15, 27): -+ size = 1 << w -+ conn.request("GET", "/") -+ with conn.getresponse() as response: -+ self.assertEqual(len(response.read()), size) -+ finally: -+ conn.close() -+ thread.join(1.0) -+ -+ def test_large_content_length_truncated(self): -+ serv = socket.create_server((HOST, 0)) -+ self.addCleanup(serv.close) -+ -+ def run_server(): -+ while True: -+ [conn, address] = serv.accept() -+ with conn: -+ conn.recv(1024) -+ if not size: -+ break -+ conn.sendall( -+ b"HTTP/1.1 200 Ok\r\n" -+ b"Content-Length: %d\r\n" -+ b"\r\n" -+ b"Text" % size) -+ -+ thread = threading.Thread(target=run_server) -+ thread.start() -+ self.addCleanup(thread.join, 1.0) -+ -+ conn = client.HTTPConnection(*serv.getsockname()) -+ try: -+ for w in range(18, 65): -+ size = 1 << w -+ conn.request("GET", "/") -+ with conn.getresponse() as response: -+ self.assertRaises(client.IncompleteRead, response.read) -+ conn.close() -+ finally: -+ conn.close() -+ size = 0 -+ conn.request("GET", "/") -+ conn.close() -+ thread.join(1.0) -+ - def test_putrequest_override_domain_validation(self): - """ - It should be possible to override the default validation -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst 2025-12-18 19:11:10.280437075 +0100 -@@ -0,0 +1,5 @@ -+Fix a potential memory denial of service in the :mod:`http.client` module. -+When connecting to a malicious server, it could cause -+an arbitrary amount of memory to be allocated. -+This could have led to symptoms including a :exc:`MemoryError`, swapping, out -+of memory (OOM) killed processes or containers, or even system crashes. diff --git a/CVE-2025-13837-plistlib-mailicious-length.patch b/CVE-2025-13837-plistlib-mailicious-length.patch deleted file mode 100644 index 41b3ab2..0000000 --- a/CVE-2025-13837-plistlib-mailicious-length.patch +++ /dev/null @@ -1,159 +0,0 @@ -From fa6d8d0f5d00fd629c5df6aabadc82d5f2a76099 Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -Date: Mon, 1 Dec 2025 17:28:15 +0200 -Subject: [PATCH] [3.12] gh-119342: Fix a potential denial of service in - plistlib (GH-119343) - -Reading a specially prepared small Plist file could cause OOM because file's -read(n) preallocates a bytes object for reading the specified amount of -data. Now plistlib reads large data by chunks, therefore the upper limit of -consumed memory is proportional to the size of the input file. -(cherry picked from commit 694922cf40aa3a28f898b5f5ee08b71b4922df70) - -Co-authored-by: Serhiy Storchaka ---- - Lib/plistlib.py | 31 +++++--- - Lib/test/test_plistlib.py | 37 +++++++++- - Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst | 5 + - 3 files changed, 59 insertions(+), 14 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst - -Index: Python-3.12.12/Lib/plistlib.py -=================================================================== ---- Python-3.12.12.orig/Lib/plistlib.py 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Lib/plistlib.py 2025-12-19 20:12:03.018693606 +0100 -@@ -73,6 +73,9 @@ - PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__) - globals().update(PlistFormat.__members__) - -+# Data larger than this will be read in chunks, to prevent extreme -+# overallocation. -+_MIN_READ_BUF_SIZE = 1 << 20 - - class UID: - def __init__(self, data): -@@ -499,12 +502,24 @@ - - return tokenL - -+ def _read(self, size): -+ cursize = min(size, _MIN_READ_BUF_SIZE) -+ data = self._fp.read(cursize) -+ while True: -+ if len(data) != cursize: -+ raise InvalidFileException -+ if cursize == size: -+ return data -+ delta = min(cursize, size - cursize) -+ data += self._fp.read(delta) -+ cursize += delta -+ - def _read_ints(self, n, size): -- data = self._fp.read(size * n) -+ data = self._read(size * n) - if size in _BINARY_FORMAT: - return struct.unpack(f'>{n}{_BINARY_FORMAT[size]}', data) - else: -- if not size or len(data) != size * n: -+ if not size: - raise InvalidFileException() - return tuple(int.from_bytes(data[i: i + size], 'big') - for i in range(0, size * n, size)) -@@ -561,22 +576,16 @@ - - elif tokenH == 0x40: # data - s = self._get_size(tokenL) -- result = self._fp.read(s) -- if len(result) != s: -- raise InvalidFileException() -+ result = self._read(s) - - elif tokenH == 0x50: # ascii string - s = self._get_size(tokenL) -- data = self._fp.read(s) -- if len(data) != s: -- raise InvalidFileException() -+ data = self._read(s) - result = data.decode('ascii') - - elif tokenH == 0x60: # unicode string - s = self._get_size(tokenL) * 2 -- data = self._fp.read(s) -- if len(data) != s: -- raise InvalidFileException() -+ data = self._read(s) - result = data.decode('utf-16be') - - elif tokenH == 0x80: # UID -Index: Python-3.12.12/Lib/test/test_plistlib.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_plistlib.py 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Lib/test/test_plistlib.py 2025-12-19 20:12:03.018920871 +0100 -@@ -841,8 +841,7 @@ - - class TestBinaryPlistlib(unittest.TestCase): - -- @staticmethod -- def decode(*objects, offset_size=1, ref_size=1): -+ def build(self, *objects, offset_size=1, ref_size=1): - data = [b'bplist00'] - offset = 8 - offsets = [] -@@ -854,7 +853,11 @@ - len(objects), 0, offset) - data.extend(offsets) - data.append(tail) -- return plistlib.loads(b''.join(data), fmt=plistlib.FMT_BINARY) -+ return b''.join(data) -+ -+ def decode(self, *objects, offset_size=1, ref_size=1): -+ data = self.build(*objects, offset_size=offset_size, ref_size=ref_size) -+ return plistlib.loads(data, fmt=plistlib.FMT_BINARY) - - def test_nonstandard_refs_size(self): - # Issue #21538: Refs and offsets are 24-bit integers -@@ -963,6 +966,34 @@ - with self.assertRaises(plistlib.InvalidFileException): - plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY) - -+ def test_truncated_large_data(self): -+ self.addCleanup(os_helper.unlink, os_helper.TESTFN) -+ def check(data): -+ with open(os_helper.TESTFN, 'wb') as f: -+ f.write(data) -+ # buffered file -+ with open(os_helper.TESTFN, 'rb') as f: -+ with self.assertRaises(plistlib.InvalidFileException): -+ plistlib.load(f, fmt=plistlib.FMT_BINARY) -+ # unbuffered file -+ with open(os_helper.TESTFN, 'rb', buffering=0) as f: -+ with self.assertRaises(plistlib.InvalidFileException): -+ plistlib.load(f, fmt=plistlib.FMT_BINARY) -+ for w in range(20, 64): -+ s = 1 << w -+ # data -+ check(self.build(b'\x4f\x13' + s.to_bytes(8, 'big'))) -+ # ascii string -+ check(self.build(b'\x5f\x13' + s.to_bytes(8, 'big'))) -+ # unicode string -+ check(self.build(b'\x6f\x13' + s.to_bytes(8, 'big'))) -+ # array -+ check(self.build(b'\xaf\x13' + s.to_bytes(8, 'big'))) -+ # dict -+ check(self.build(b'\xdf\x13' + s.to_bytes(8, 'big'))) -+ # number of objects -+ check(b'bplist00' + struct.pack('>6xBBQQQ', 1, 1, s, 0, 8)) -+ - - class TestKeyedArchive(unittest.TestCase): - def test_keyed_archive_data(self): -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst 2025-12-19 20:12:03.019148207 +0100 -@@ -0,0 +1,5 @@ -+Fix a potential memory denial of service in the :mod:`plistlib` module. -+When reading a Plist file received from untrusted source, it could cause -+an arbitrary amount of memory to be allocated. -+This could have led to symptoms including a :exc:`MemoryError`, swapping, out -+of memory (OOM) killed processes or containers, or even system crashes. diff --git a/CVE-2025-15282-urllib-ctrl-chars.patch b/CVE-2025-15282-urllib-ctrl-chars.patch deleted file mode 100644 index 3e78e8f..0000000 --- a/CVE-2025-15282-urllib-ctrl-chars.patch +++ /dev/null @@ -1,64 +0,0 @@ -From f336af1c4b103297de1322bbe00f920f3e58b899 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Tue, 20 Jan 2026 14:45:58 -0600 -Subject: [PATCH 1/2] [3.12] gh-143925: Reject control characters in data: URL - mediatypes (cherry picked from commit - f25509e78e8be6ea73c811ac2b8c928c28841b9f) (cherry picked from commit - 2c9c746077d8119b5bcf5142316992e464594946) - -Co-authored-by: Seth Michael Larson ---- - Lib/test/test_urllib.py | 8 ++++++++ - Lib/urllib/request.py | 5 +++++ - Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst | 1 + - 3 files changed, 14 insertions(+) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst - -Index: Python-3.12.12/Lib/test/test_urllib.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_urllib.py 2026-02-10 22:15:06.355594386 +0100 -+++ Python-3.12.12/Lib/test/test_urllib.py 2026-02-10 22:18:23.820760279 +0100 -@@ -12,6 +12,7 @@ - from test.support import os_helper - from test.support import socket_helper - from test.support import warnings_helper -+from test.support import control_characters_c0 - import os - try: - import ssl -@@ -688,6 +689,13 @@ - # missing padding character - self.assertRaises(ValueError,urllib.request.urlopen,'data:;base64,Cg=') - -+ def test_invalid_mediatype(self): -+ for c0 in control_characters_c0(): -+ self.assertRaises(ValueError,urllib.request.urlopen, -+ f'data:text/html;{c0},data') -+ for c0 in control_characters_c0(): -+ self.assertRaises(ValueError,urllib.request.urlopen, -+ f'data:text/html{c0};base64,ZGF0YQ==') - - class urlretrieve_FileTests(unittest.TestCase): - """Test urllib.urlretrieve() on local files""" -Index: Python-3.12.12/Lib/urllib/request.py -=================================================================== ---- Python-3.12.12.orig/Lib/urllib/request.py 2026-02-10 22:15:06.739534061 +0100 -+++ Python-3.12.12/Lib/urllib/request.py 2026-02-10 22:18:23.819325524 +0100 -@@ -1655,6 +1655,11 @@ - scheme, data = url.split(":",1) - mediatype, data = data.split(",",1) - -+ # Disallow control characters within mediatype. -+ if re.search(r"[\x00-\x1F\x7F]", mediatype): -+ raise ValueError( -+ "Control characters not allowed in data: mediatype") -+ - # even base64 encoded data URLs might be quoted so unquote in any case: - data = unquote_to_bytes(data) - if mediatype.endswith(";base64"): -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst 2026-02-10 22:18:23.819830797 +0100 -@@ -0,0 +1 @@ -+Reject control characters in ``data:`` URL media types. diff --git a/CVE-2025-15366-imap-ctrl-chars.patch b/CVE-2025-15366-imap-ctrl-chars.patch index e42abab..6f091da 100644 --- a/CVE-2025-15366-imap-ctrl-chars.patch +++ b/CVE-2025-15366-imap-ctrl-chars.patch @@ -8,10 +8,10 @@ Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) -Index: Python-3.12.12/Lib/imaplib.py +Index: Python-3.12.13/Lib/imaplib.py =================================================================== ---- Python-3.12.12.orig/Lib/imaplib.py 2026-02-10 22:15:03.417592955 +0100 -+++ Python-3.12.12/Lib/imaplib.py 2026-02-10 22:18:02.094605035 +0100 +--- Python-3.12.13.orig/Lib/imaplib.py 2026-03-06 20:21:13.076797807 +0100 ++++ Python-3.12.13/Lib/imaplib.py 2026-03-06 20:25:14.549622415 +0100 @@ -132,7 +132,7 @@ # We compile these in _mode_xxx. _Literal = br'.*{(?P\d+)}$' @@ -30,9 +30,9 @@ Index: Python-3.12.12/Lib/imaplib.py data = data + b' ' + arg literal = self.literal -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +Index: Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst 2026-02-10 22:18:02.095167966 +0100 ++++ Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst 2026-03-06 20:25:14.550097371 +0100 @@ -0,0 +1 @@ +Reject control characters in IMAP commands. diff --git a/CVE-2025-15367-poplib-ctrl-chars.patch b/CVE-2025-15367-poplib-ctrl-chars.patch index 4366206..dd77b13 100644 --- a/CVE-2025-15367-poplib-ctrl-chars.patch +++ b/CVE-2025-15367-poplib-ctrl-chars.patch @@ -9,10 +9,10 @@ Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst | 1 + 3 files changed, 11 insertions(+) -Index: Python-3.12.12/Lib/poplib.py +Index: Python-3.12.13/Lib/poplib.py =================================================================== ---- Python-3.12.12.orig/Lib/poplib.py 2026-02-11 23:46:29.442215955 +0100 -+++ Python-3.12.12/Lib/poplib.py 2026-02-11 23:46:46.713251058 +0100 +--- Python-3.12.13.orig/Lib/poplib.py 2026-03-06 20:21:13.491889752 +0100 ++++ Python-3.12.13/Lib/poplib.py 2026-03-06 20:25:33.388287765 +0100 @@ -122,6 +122,8 @@ def _putcmd(self, line): if self._debugging: print('*cmd*', repr(line)) @@ -22,10 +22,10 @@ Index: Python-3.12.12/Lib/poplib.py self._putline(line) -Index: Python-3.12.12/Lib/test/test_poplib.py +Index: Python-3.12.13/Lib/test/test_poplib.py =================================================================== ---- Python-3.12.12.orig/Lib/test/test_poplib.py 2026-02-11 23:46:31.636412813 +0100 -+++ Python-3.12.12/Lib/test/test_poplib.py 2026-02-11 23:46:46.713442229 +0100 +--- Python-3.12.13.orig/Lib/test/test_poplib.py 2026-03-06 20:21:15.497803691 +0100 ++++ Python-3.12.13/Lib/test/test_poplib.py 2026-03-06 20:25:33.389775036 +0100 @@ -17,6 +17,7 @@ from test.support import threading_helper from test.support import asynchat @@ -48,9 +48,9 @@ Index: Python-3.12.12/Lib/test/test_poplib.py @requires_ssl def test_stls_capa(self): capa = self.client.capa() -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +Index: Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst 2026-02-11 23:46:46.713620996 +0100 ++++ Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst 2026-03-06 20:25:33.390103395 +0100 @@ -0,0 +1 @@ +Reject control characters in POP3 commands. diff --git a/CVE-2025-6075-expandvars-perf-degrad.patch b/CVE-2025-6075-expandvars-perf-degrad.patch deleted file mode 100644 index f867760..0000000 --- a/CVE-2025-6075-expandvars-perf-degrad.patch +++ /dev/null @@ -1,382 +0,0 @@ -From 122a417f8000eb904a3cac9aacf4de8d288d7148 Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -Date: Fri, 31 Oct 2025 15:49:51 +0200 -Subject: [PATCH 1/2] [3.12] gh-136065: Fix quadratic complexity in - os.path.expandvars() (GH-134952) (cherry picked from commit - f029e8db626ddc6e3a3beea4eff511a71aaceb5c) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Co-authored-by: Serhiy Storchaka -Co-authored-by: Łukasz Langa ---- - Lib/ntpath.py | 126 ++++++------------ - Lib/posixpath.py | 43 +++--- - Lib/test/test_genericpath.py | 14 ++ - Lib/test/test_ntpath.py | 22 ++- - ...-05-30-22-33-27.gh-issue-136065.bu337o.rst | 1 + - 5 files changed, 93 insertions(+), 113 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst - -diff --git a/Lib/ntpath.py b/Lib/ntpath.py -index 1bef630bd9c0ff..393d358b0afb8c 100644 ---- a/Lib/ntpath.py -+++ b/Lib/ntpath.py -@@ -409,17 +409,23 @@ def expanduser(path): - # XXX With COMMAND.COM you can use any characters in a variable name, - # XXX except '^|<>='. - -+_varpattern = r"'[^']*'?|%(%|[^%]*%?)|\$(\$|[-\w]+|\{[^}]*\}?)" -+_varsub = None -+_varsubb = None -+ - def expandvars(path): - """Expand shell variables of the forms $var, ${var} and %var%. - - Unknown variables are left unchanged.""" - path = os.fspath(path) -+ global _varsub, _varsubb - if isinstance(path, bytes): - if b'$' not in path and b'%' not in path: - return path -- import string -- varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii') -- quote = b'\'' -+ if not _varsubb: -+ import re -+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub -+ sub = _varsubb - percent = b'%' - brace = b'{' - rbrace = b'}' -@@ -428,94 +434,44 @@ def expandvars(path): - else: - if '$' not in path and '%' not in path: - return path -- import string -- varchars = string.ascii_letters + string.digits + '_-' -- quote = '\'' -+ if not _varsub: -+ import re -+ _varsub = re.compile(_varpattern, re.ASCII).sub -+ sub = _varsub - percent = '%' - brace = '{' - rbrace = '}' - dollar = '$' - environ = os.environ -- res = path[:0] -- index = 0 -- pathlen = len(path) -- while index < pathlen: -- c = path[index:index+1] -- if c == quote: # no expansion within single quotes -- path = path[index + 1:] -- pathlen = len(path) -- try: -- index = path.index(c) -- res += c + path[:index + 1] -- except ValueError: -- res += c + path -- index = pathlen - 1 -- elif c == percent: # variable or '%' -- if path[index + 1:index + 2] == percent: -- res += c -- index += 1 -- else: -- path = path[index+1:] -- pathlen = len(path) -- try: -- index = path.index(percent) -- except ValueError: -- res += percent + path -- index = pathlen - 1 -- else: -- var = path[:index] -- try: -- if environ is None: -- value = os.fsencode(os.environ[os.fsdecode(var)]) -- else: -- value = environ[var] -- except KeyError: -- value = percent + var + percent -- res += value -- elif c == dollar: # variable or '$$' -- if path[index + 1:index + 2] == dollar: -- res += c -- index += 1 -- elif path[index + 1:index + 2] == brace: -- path = path[index+2:] -- pathlen = len(path) -- try: -- index = path.index(rbrace) -- except ValueError: -- res += dollar + brace + path -- index = pathlen - 1 -- else: -- var = path[:index] -- try: -- if environ is None: -- value = os.fsencode(os.environ[os.fsdecode(var)]) -- else: -- value = environ[var] -- except KeyError: -- value = dollar + brace + var + rbrace -- res += value -- else: -- var = path[:0] -- index += 1 -- c = path[index:index + 1] -- while c and c in varchars: -- var += c -- index += 1 -- c = path[index:index + 1] -- try: -- if environ is None: -- value = os.fsencode(os.environ[os.fsdecode(var)]) -- else: -- value = environ[var] -- except KeyError: -- value = dollar + var -- res += value -- if c: -- index -= 1 -+ -+ def repl(m): -+ lastindex = m.lastindex -+ if lastindex is None: -+ return m[0] -+ name = m[lastindex] -+ if lastindex == 1: -+ if name == percent: -+ return name -+ if not name.endswith(percent): -+ return m[0] -+ name = name[:-1] - else: -- res += c -- index += 1 -- return res -+ if name == dollar: -+ return name -+ if name.startswith(brace): -+ if not name.endswith(rbrace): -+ return m[0] -+ name = name[1:-1] -+ -+ try: -+ if environ is None: -+ return os.fsencode(os.environ[os.fsdecode(name)]) -+ else: -+ return environ[name] -+ except KeyError: -+ return m[0] -+ -+ return sub(repl, path) - - - # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. -diff --git a/Lib/posixpath.py b/Lib/posixpath.py -index 90a6f545f90529..6306f14f53491b 100644 ---- a/Lib/posixpath.py -+++ b/Lib/posixpath.py -@@ -314,42 +314,41 @@ def expanduser(path): - # This expands the forms $variable and ${variable} only. - # Non-existent variables are left unchanged. - --_varprog = None --_varprogb = None -+_varpattern = r'\$(\w+|\{[^}]*\}?)' -+_varsub = None -+_varsubb = None - - def expandvars(path): - """Expand shell variables of form $var and ${var}. Unknown variables - are left unchanged.""" - path = os.fspath(path) -- global _varprog, _varprogb -+ global _varsub, _varsubb - if isinstance(path, bytes): - if b'$' not in path: - return path -- if not _varprogb: -+ if not _varsubb: - import re -- _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) -- search = _varprogb.search -+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub -+ sub = _varsubb - start = b'{' - end = b'}' - environ = getattr(os, 'environb', None) - else: - if '$' not in path: - return path -- if not _varprog: -+ if not _varsub: - import re -- _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) -- search = _varprog.search -+ _varsub = re.compile(_varpattern, re.ASCII).sub -+ sub = _varsub - start = '{' - end = '}' - environ = os.environ -- i = 0 -- while True: -- m = search(path, i) -- if not m: -- break -- i, j = m.span(0) -- name = m.group(1) -- if name.startswith(start) and name.endswith(end): -+ -+ def repl(m): -+ name = m[1] -+ if name.startswith(start): -+ if not name.endswith(end): -+ return m[0] - name = name[1:-1] - try: - if environ is None: -@@ -357,13 +356,11 @@ def expandvars(path): - else: - value = environ[name] - except KeyError: -- i = j -+ return m[0] - else: -- tail = path[j:] -- path = path[:i] + value -- i = len(path) -- path += tail -- return path -+ return value -+ -+ return sub(repl, path) - - - # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. -diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py -index 3eefb722b81e55..1cec587e875888 100644 ---- a/Lib/test/test_genericpath.py -+++ b/Lib/test/test_genericpath.py -@@ -7,6 +7,7 @@ - import sys - import unittest - import warnings -+from test import support - from test.support import is_emscripten - from test.support import os_helper - from test.support import warnings_helper -@@ -443,6 +444,19 @@ def check(value, expected): - os.fsencode('$bar%s bar' % nonascii)) - check(b'$spam}bar', os.fsencode('%s}bar' % nonascii)) - -+ @support.requires_resource('cpu') -+ def test_expandvars_large(self): -+ expandvars = self.pathmodule.expandvars -+ with os_helper.EnvironmentVarGuard() as env: -+ env.clear() -+ env["A"] = "B" -+ n = 100_000 -+ self.assertEqual(expandvars('$A'*n), 'B'*n) -+ self.assertEqual(expandvars('${A}'*n), 'B'*n) -+ self.assertEqual(expandvars('$A!'*n), 'B!'*n) -+ self.assertEqual(expandvars('${A}A'*n), 'BA'*n) -+ self.assertEqual(expandvars('${'*10*n), '${'*10*n) -+ - def test_abspath(self): - self.assertIn("foo", self.pathmodule.abspath("foo")) - with warnings.catch_warnings(): -diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py -index ced9dc4fffb41e..72f89ebb21c478 100644 ---- a/Lib/test/test_ntpath.py -+++ b/Lib/test/test_ntpath.py -@@ -7,8 +7,7 @@ - import unittest - import warnings - from ntpath import ALLOW_MISSING --from test.support import cpython_only, os_helper --from test.support import TestFailed, is_emscripten -+from test.support import os_helper, is_emscripten - from test.support.os_helper import FakePath - from test import test_genericpath - from tempfile import TemporaryFile -@@ -58,7 +57,7 @@ def tester(fn, wantResult): - fn = fn.replace("\\", "\\\\") - gotResult = eval(fn) - if wantResult != gotResult and _norm(wantResult) != _norm(gotResult): -- raise TestFailed("%s should return: %s but returned: %s" \ -+ raise support.TestFailed("%s should return: %s but returned: %s" \ - %(str(fn), str(wantResult), str(gotResult))) - - # then with bytes -@@ -74,7 +73,7 @@ def tester(fn, wantResult): - warnings.simplefilter("ignore", DeprecationWarning) - gotResult = eval(fn) - if _norm(wantResult) != _norm(gotResult): -- raise TestFailed("%s should return: %s but returned: %s" \ -+ raise support.TestFailed("%s should return: %s but returned: %s" \ - %(str(fn), str(wantResult), repr(gotResult))) - - -@@ -882,6 +881,19 @@ def check(value, expected): - check('%spam%bar', '%sbar' % nonascii) - check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii) - -+ @support.requires_resource('cpu') -+ def test_expandvars_large(self): -+ expandvars = ntpath.expandvars -+ with os_helper.EnvironmentVarGuard() as env: -+ env.clear() -+ env["A"] = "B" -+ n = 100_000 -+ self.assertEqual(expandvars('%A%'*n), 'B'*n) -+ self.assertEqual(expandvars('%A%A'*n), 'BA'*n) -+ self.assertEqual(expandvars("''"*n + '%%'), "''"*n + '%') -+ self.assertEqual(expandvars("%%"*n), "%"*n) -+ self.assertEqual(expandvars("$$"*n), "$"*n) -+ - def test_expanduser(self): - tester('ntpath.expanduser("test")', 'test') - -@@ -1207,7 +1219,7 @@ def test_con_device(self): - self.assertTrue(os.path.exists(r"\\.\CON")) - - @unittest.skipIf(sys.platform != 'win32', "Fast paths are only for win32") -- @cpython_only -+ @support.cpython_only - def test_fast_paths_in_use(self): - # There are fast paths of these functions implemented in posixmodule.c. - # Confirm that they are being used, and not the Python fallbacks in -diff --git a/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst b/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst -new file mode 100644 -index 00000000000000..1d152bb5318380 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst -@@ -0,0 +1 @@ -+Fix quadratic complexity in :func:`os.path.expandvars`. - -From 27eb90f676ced2a2a6f2a3ea9d0555d045a0d976 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C5=81ukasz=20Langa?= -Date: Fri, 31 Oct 2025 17:32:52 +0100 -Subject: [PATCH 2/2] Oops - ---- - Lib/test/test_ntpath.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py -index 72f89ebb21c478..7c42d4f5894788 100644 ---- a/Lib/test/test_ntpath.py -+++ b/Lib/test/test_ntpath.py -@@ -7,6 +7,7 @@ - import unittest - import warnings - from ntpath import ALLOW_MISSING -+from test import support - from test.support import os_helper, is_emscripten - from test.support.os_helper import FakePath - from test import test_genericpath diff --git a/CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch b/CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch deleted file mode 100644 index 1ce4e2f..0000000 --- a/CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 9729bdf210967c806f3364c76663fc2ade58e389 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Tue, 20 Jan 2026 15:23:42 -0600 -Subject: [PATCH] gh-143919: Reject control characters in http cookies (cherry - picked from commit 95746b3a13a985787ef53b977129041971ed7f70) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Co-authored-by: Seth Michael Larson -Co-authored-by: Bartosz Sławecki -Co-authored-by: sobolevn ---- - Doc/library/http.cookies.rst | 4 - Lib/http/cookies.py | 25 ++++ - Lib/test/test_http_cookies.py | 52 +++++++++- - Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst | 1 - 4 files changed, 73 insertions(+), 9 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst - -Index: Python-3.12.12/Doc/library/http.cookies.rst -=================================================================== ---- Python-3.12.12.orig/Doc/library/http.cookies.rst 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Doc/library/http.cookies.rst 2026-02-10 22:17:53.970413039 +0100 -@@ -272,9 +272,9 @@ - Set-Cookie: chips=ahoy - Set-Cookie: vienna=finger - >>> C = cookies.SimpleCookie() -- >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";') -+ >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=;";') - >>> print(C) -- Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;" -+ Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;" - >>> C = cookies.SimpleCookie() - >>> C["oreo"] = "doublestuff" - >>> C["oreo"]["path"] = "/" -Index: Python-3.12.12/Lib/http/cookies.py -=================================================================== ---- Python-3.12.12.orig/Lib/http/cookies.py 2026-02-10 22:15:03.102916960 +0100 -+++ Python-3.12.12/Lib/http/cookies.py 2026-02-10 22:17:53.970584713 +0100 -@@ -87,9 +87,9 @@ - such trickeries do not confuse it. - - >>> C = cookies.SimpleCookie() -- >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";') -+ >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=;";') - >>> print(C) -- Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;" -+ Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;" - - Each element of the Cookie also supports all of the RFC 2109 - Cookie attributes. Here's an example which sets the Path -@@ -170,6 +170,15 @@ - }) - - _is_legal_key = re.compile('[%s]+' % re.escape(_LegalChars)).fullmatch -+_control_character_re = re.compile(r'[\x00-\x1F\x7F]') -+ -+ -+def _has_control_character(*val): -+ """Detects control characters within a value. -+ Supports any type, as header values can be any type. -+ """ -+ return any(_control_character_re.search(str(v)) for v in val) -+ - - def _quote(str): - r"""Quote a string for use in a cookie header. -@@ -292,12 +301,16 @@ - K = K.lower() - if not K in self._reserved: - raise CookieError("Invalid attribute %r" % (K,)) -+ if _has_control_character(K, V): -+ raise CookieError(f"Control characters are not allowed in cookies {K!r} {V!r}") - dict.__setitem__(self, K, V) - - def setdefault(self, key, val=None): - key = key.lower() - if key not in self._reserved: - raise CookieError("Invalid attribute %r" % (key,)) -+ if _has_control_character(key, val): -+ raise CookieError("Control characters are not allowed in cookies %r %r" % (key, val,)) - return dict.setdefault(self, key, val) - - def __eq__(self, morsel): -@@ -333,6 +346,9 @@ - raise CookieError('Attempt to set a reserved key %r' % (key,)) - if not _is_legal_key(key): - raise CookieError('Illegal key %r' % (key,)) -+ if _has_control_character(key, val, coded_val): -+ raise CookieError( -+ "Control characters are not allowed in cookies %r %r %r" % (key, val, coded_val,)) - - # It's a good key, so save it. - self._key = key -@@ -486,7 +502,10 @@ - result = [] - items = sorted(self.items()) - for key, value in items: -- result.append(value.output(attrs, header)) -+ value_output = value.output(attrs, header) -+ if _has_control_character(value_output): -+ raise CookieError("Control characters are not allowed in cookies") -+ result.append(value_output) - return sep.join(result) - - __str__ = output -Index: Python-3.12.12/Lib/test/test_http_cookies.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_http_cookies.py 2026-02-10 22:15:05.120676729 +0100 -+++ Python-3.12.12/Lib/test/test_http_cookies.py 2026-02-10 22:17:53.970780833 +0100 -@@ -17,10 +17,10 @@ - 'repr': "", - 'output': 'Set-Cookie: chips=ahoy\nSet-Cookie: vienna=finger'}, - -- {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"', -- 'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=\012;'}, -- 'repr': '''''', -- 'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"'}, -+ {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=;"', -+ 'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=;'}, -+ 'repr': '''''', -+ 'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; fudge=;"'}, - - # Check illegal cookies that have an '=' char in an unquoted value - {'data': 'keebler=E=mc2', -@@ -563,6 +563,50 @@ - r'Set-Cookie: key=coded_val; ' - r'expires=\w+, \d+ \w+ \d+ \d+:\d+:\d+ \w+') - -+ def test_control_characters(self): -+ for c0 in support.control_characters_c0(): -+ morsel = cookies.Morsel() -+ -+ # .__setitem__() -+ with self.assertRaises(cookies.CookieError): -+ morsel[c0] = "val" -+ with self.assertRaises(cookies.CookieError): -+ morsel["path"] = c0 -+ -+ # .setdefault() -+ with self.assertRaises(cookies.CookieError): -+ morsel.setdefault("path", c0) -+ with self.assertRaises(cookies.CookieError): -+ morsel.setdefault(c0, "val") -+ -+ # .set() -+ with self.assertRaises(cookies.CookieError): -+ morsel.set(c0, "val", "coded-value") -+ with self.assertRaises(cookies.CookieError): -+ morsel.set("path", c0, "coded-value") -+ with self.assertRaises(cookies.CookieError): -+ morsel.set("path", "val", c0) -+ -+ def test_control_characters_output(self): -+ # Tests that even if the internals of Morsel are modified -+ # that a call to .output() has control character safeguards. -+ for c0 in support.control_characters_c0(): -+ morsel = cookies.Morsel() -+ morsel.set("key", "value", "coded-value") -+ morsel._key = c0 # Override private variable. -+ cookie = cookies.SimpleCookie() -+ cookie["cookie"] = morsel -+ with self.assertRaises(cookies.CookieError): -+ cookie.output() -+ -+ morsel = cookies.Morsel() -+ morsel.set("key", "value", "coded-value") -+ morsel._coded_value = c0 # Override private variable. -+ cookie = cookies.SimpleCookie() -+ cookie["cookie"] = morsel -+ with self.assertRaises(cookies.CookieError): -+ cookie.output() -+ - - def load_tests(loader, tests, pattern): - tests.addTest(doctest.DocTestSuite(cookies)) -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst 2026-02-10 22:17:53.970970320 +0100 -@@ -0,0 +1 @@ -+Reject control characters in :class:`http.cookies.Morsel` fields and values. diff --git a/CVE-2026-0865-wsgiref-ctrl-chars.patch b/CVE-2026-0865-wsgiref-ctrl-chars.patch deleted file mode 100644 index d189998..0000000 --- a/CVE-2026-0865-wsgiref-ctrl-chars.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 03a7342c9e2bbdab20a6d882bf334608dc7a5d4b Mon Sep 17 00:00:00 2001 -From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> -Date: Sat, 17 Jan 2026 10:23:57 -0800 -Subject: [PATCH] [3.12] gh-143916: Reject control characters in - wsgiref.headers.Headers (GH-143917) (GH-143973) - -gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) - -* Add 'test.support' fixture for C0 control characters -* gh-143916: Reject control characters in wsgiref.headers.Headers - -(cherry picked from commit f7fceed79ca1bceae8dbe5ba5bc8928564da7211) -(cherry picked from commit 22e4d55285cee52bc4dbe061324e5f30bd4dee58) - -Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> -Co-authored-by: Seth Michael Larson ---- - Lib/test/support/__init__.py | 7 +++++ - Lib/test/test_wsgiref.py | 12 +++++++++- - Lib/wsgiref/headers.py | 3 ++ - Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst | 2 + - 4 files changed, 23 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst - -Index: Python-3.12.12/Lib/test/support/__init__.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/support/__init__.py 2026-02-10 22:15:04.163026806 +0100 -+++ Python-3.12.12/Lib/test/support/__init__.py 2026-02-10 22:17:57.451276662 +0100 -@@ -2591,3 +2591,10 @@ - if self.iter_raises: - 1/0 - return self -+ -+ -+def control_characters_c0() -> list[str]: -+ """Returns a list of C0 control characters as strings. -+ C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. -+ """ -+ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] -Index: Python-3.12.12/Lib/test/test_wsgiref.py -=================================================================== ---- Python-3.12.12.orig/Lib/test/test_wsgiref.py 2026-02-10 22:15:06.432657502 +0100 -+++ Python-3.12.12/Lib/test/test_wsgiref.py 2026-02-10 22:17:57.451566378 +0100 -@@ -1,6 +1,6 @@ - from unittest import mock - from test import support --from test.support import socket_helper -+from test.support import socket_helper, control_characters_c0 - from test.test_httpservers import NoLogRequestHandler - from unittest import TestCase - from wsgiref.util import setup_testing_defaults -@@ -503,6 +503,16 @@ - '\r\n' - ) - -+ def testRaisesControlCharacters(self): -+ headers = Headers() -+ for c0 in control_characters_c0(): -+ self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val") -+ self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}") -+ self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param") -+ self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param") -+ self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}") -+ -+ - class ErrorHandler(BaseCGIHandler): - """Simple handler subclass for testing BaseHandler""" - -Index: Python-3.12.12/Lib/wsgiref/headers.py -=================================================================== ---- Python-3.12.12.orig/Lib/wsgiref/headers.py 2026-02-10 22:15:06.773169140 +0100 -+++ Python-3.12.12/Lib/wsgiref/headers.py 2026-02-10 22:17:57.451729575 +0100 -@@ -9,6 +9,7 @@ - # existence of which force quoting of the parameter value. - import re - tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') -+_control_chars_re = re.compile(r'[\x00-\x1F\x7F]') - - def _formatparam(param, value=None, quote=1): - """Convenience function to format and return a key=value pair. -@@ -41,6 +42,8 @@ - def _convert_string_type(self, value): - """Convert/check value type.""" - if type(value) is str: -+ if _control_chars_re.search(value): -+ raise ValueError("Control characters not allowed in headers") - return value - raise AssertionError("Header names/values must be" - " of type str (got {0})".format(repr(value))) -Index: Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst 2026-02-10 22:17:57.451848490 +0100 -@@ -0,0 +1,2 @@ -+Reject C0 control characters within wsgiref.headers.Headers fields, values, -+and parameters. diff --git a/Python-3.12.12.tar.xz b/Python-3.12.12.tar.xz deleted file mode 100644 index a5676e8..0000000 --- a/Python-3.12.12.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fb85a13414b028c49ba18bbd523c2d055a30b56b18b92ce454ea2c51edc656c4 -size 20798712 diff --git a/Python-3.12.12.tar.xz.asc b/Python-3.12.12.tar.xz.asc deleted file mode 100644 index 9e6c514..0000000 --- a/Python-3.12.12.tar.xz.asc +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQKTBAABCgB9FiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmjnnr1fFIAAAAAALgAo -aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDcx -Njk2MDVGNjJDNzUxMzU2RDA1NEEyNkE4MjFFNjgwRTVGQTYzMDUACgkQqCHmgOX6 -YwXF3Q//VrreGa+P8lvp9UMjoj/YquKPwLqjzzAWf5vzHipkebdiESsB1HfGu04k -Jw+ctTnXHf/12u0W7ijv+56JtcJFqEzh8yGokWqOzc99rpCeCY9qtuwaVYtZrTNx -wepRaDAHdhP4Z2kLPDiE6pCXu2NIR5wHqHjQ8JGmprhASc07uxEhNN/gucVR2Sbr -cCfC9rHfHkdhoPpZRRbcraAaxPGL3VyBXf7HuYbHhf4GuF9EVDlFg5I0BzHCKJDd -ebPXYHvsoDgrMMqPXiX/YkGNByf3Ze6KZTNSGICy8SDzIzZgpmtOe5rzvlOXJBZZ -SVfX8SqP4Ufml+MfJrGEx30S9reYYvnyTSmttpbDznonROKPEZOuDt08+CG3yR+T -o5RdIneWmGXRf1mBrFKH9Br5tfOd+YeldfxdoQgla2fFHFVRnab1lsZFOC/HZ5z2 -Q3rPfVMDYKO8yoIKqv0BUzlkn9wYphCWoPHq0Y+SGjcP+Zh5qRTMqZYIaGekhWmx -86egHHVqedMI0Q9hvgIEirupVJ1q34FZn2+3sEka9hdOie9aNHXWTmgWCGDm46qj -qC9tT/jkMzWIY2Y4RdVDMdSCb7HkBEl1eAANq511gJ+eSWAXbP1sVrQoiAQY+EkC -Yu2ceZYsl9i6zm7i/QaU/mOGB7xMZhMQLZBnZTHSzAZo/pBN7y8= -=RuLK ------END PGP SIGNATURE----- diff --git a/Python-3.12.12.tar.xz.sigstore b/Python-3.12.12.tar.xz.sigstore deleted file mode 100644 index bcab32a..0000000 --- a/Python-3.12.12.tar.xz.sigstore +++ /dev/null @@ -1 +0,0 @@ -{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICyjCCAlCgAwIBAgIUa7XmzWlmoxbdaf7Bd0cb7k2SJX0wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUxMDA5MTEzOTEwWhcNMjUxMDA5MTE0OTEwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnnBupfHW0kIyKIch4g4bg/VMzmQSN3W+fDXSBXPHKVV01duW4mnJBNAx8dOjaDQJbbGLCL3nHReR6AHY5EzzWKOCAW8wggFrMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUxS1GFV6/403CJB2LIriD0Yxys+kwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0RAQH/BBUwE4ERdGhvbWFzQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGZyMSWqQAABAMARzBFAiEAgP3Zja0sZ42WlEujGWIbBp+3AemF4BPwFlVMLG/criwCIDSK9BOHosQgvpZnN+hpQrqZdHZ7j1QXaxWfcERObDGrMAoGCCqGSM49BAMDA2gAMGUCMC/Fx5Bbae7C7w5CjzPgAIRB8sAV5THF7EynHjFxBqjwYhiMblyn5lzwpTsSpcGyiQIxAMtPBAMZXbJeY8LL/rTmrqaS+gvUCFZe430pf/7njbi+vMTsnX6lbyDW6+MBPf2w0Q=="}, "tlogEntries": [{"logIndex": "597445409", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1760009951", "inclusionPromise": {"signedEntryTimestamp": "MEQCICmAn/SSLFYafnAtkPRYmvBAv34ZqQsxnCKxA6lvOwtIAiADgWJmj7xnSimwJjyYMND/62BSa6VAn+yiurqa+3sFbg=="}, "inclusionProof": {"logIndex": "475541147", "rootHash": "NtKq0OO26YDo37dp00CxEkih9ardFvhT06bm+f1SQDE=", "treeSize": "475541154", "hashes": ["NslcefFuKuND6JRNbUSPjLrHeL0W18bCD4VhxfCcQKk=", "A0S2uABqcbgE1HPfloLBAk0TlXFJVl7yLEBondSsQ0c=", "6sWxX6Qc03LZeNbyN5W9cj7IZtqLYjkxFKvRS3ynzso=", "sdBvJFo0UwZVcXbz5NwqW/k4wRKwjiBjYIlN9G6hzXc=", "HSc04gOheRI34V7k9W+RDSDZFEf2I9JjEEOdGOMAUCA=", "C0KrXbTnn0FjHCn6Pk8TOEPndNLUliSsS1kLpaoeFho=", "/lb6eJIa9/379KwZZThJl+TJzpB0p9sLsW59J4AkleA=", "60XcwfvS6KRVEutb85dCHmflKO/pCJu3wP/wi71Hjjw=", "T5+n1/blJViw8vobIXjJuar7GB5qkWPWxuPI4TLuIus=", "N/HdEEbPrOhis60vsOpblzzFJ5Gn0VF1X5o/a5zj5ho=", "5iV4XGoB9mnKM5YryHN+GB7tIaTkjbMhbGbF01zhzKU=", "qXhJobQjWl6SO/pue3trUW2uL4jXx24Ip7lpd4hc5bU=", "56ObhlROm9L8Q4JyN+mxEQ5pZD5QdobB1xZFIeL0lVg=", "EGaD/cNavzxGYLx1Gl0uNNWBZvyXlSHSdlIeH7m+63A=", "2Wv4GiithwNukRKV06clevnQQYCzXmSS/+/OJtXgsXQ=", "1mfy94KpcItqshH9+gwqV6jccupcaMpVsF28New8zDY=", "vS7O4ozHIQZJWBiov+mkpI27GE8zAmVCEkRcP3NDyNE="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n475541154\nNtKq0OO26YDo37dp00CxEkih9ardFvhT06bm+f1SQDE=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiBAXkd6xMHjC/fa3mQGVYRGINSGMy5E39T2cwLfMJUCdAIhAJ8pLs5eiFWKL+RH/M/yyicyskpEIjumbkignFyjP+fn\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJmYjg1YTEzNDE0YjAyOGM0OWJhMThiYmQ1MjNjMmQwNTVhMzBiNTZiMThiOTJjZTQ1NGVhMmM1MWVkYzY1NmM0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNzSysxcVRmNGZHd2I1eTBuaHpiQXdKa1hucGUydDYzZU96a3VrQ2Q5bFNRSWdDTzNRb3huTFc2b0FyMk0yMFMvL3k4aURVS0VHZTNwaXBMd0MvK3ptTG5BPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjVha05EUVd4RFowRjNTVUpCWjBsVllUZFliWHBYYkcxdmVHSmtZV1kzUW1Rd1kySTNhekpUU2xnd2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZlRTFFUVRWTlZFVjZUMVJGZDFkb1kwNU5hbFY0VFVSQk5VMVVSVEJQVkVWM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ1YmtKMWNHWklWekJyU1hsTFNXTm9OR2MwWW1jdlZrMTZiVkZUVGpOWEsyWkVXRk1LUWxoUVNFdFdWakF4WkhWWE5HMXVTa0pPUVhnNFpFOXFZVVJSU21KaVIweERURE51U0ZKbFVqWkJTRmsxUlhwNlYwdFBRMEZYT0hkblowWnlUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlY0VXpGSENrWldOaTgwTURORFNrSXlURWx5YVVRd1dYaDVjeXRyZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoM1dVUldVakJTUVZGSUwwSkNWWGRGTkVWU1pFZG9kbUpYUm5wUlNFSTFaRWRvZG1KcE5YWmpiV04zUzFGWlMwdDNXVUpDUVVkRWRucEJRZ3BCVVZGaVlVaFNNR05JVFRaTWVUbG9XVEpPZG1SWE5UQmplVFZ1WWpJNWJtSkhWWFZaTWpsMFRVTnpSME5wYzBkQlVWRkNaemM0ZDBGUlowVklVWGRpQ21GSVVqQmpTRTAyVEhrNWFGa3lUblprVnpVd1kzazFibUl5T1c1aVIxVjFXVEk1ZEUxSlIwdENaMjl5UW1kRlJVRmtXalZCWjFGRFFraDNSV1ZuUWpRS1FVaFpRVE5VTUhkaGMySklSVlJLYWtkU05HTnRWMk16UVhGS1MxaHlhbVZRU3pNdmFEUndlV2RET0hBM2J6UkJRVUZIV25sTlUxZHhVVUZCUWtGTlFRcFNla0pHUVdsRlFXZFFNMXBxWVRCeldqUXlWMnhGZFdwSFYwbGlRbkFyTTBGbGJVWTBRbEIzUm14V1RVeEhMMk55YVhkRFNVUlRTemxDVDBodmMxRm5Dblp3V201T0syaHdVWEp4V21SSVdqZHFNVkZZWVhoWFptTkZVazlpUkVkeVRVRnZSME5EY1VkVFRUUTVRa0ZOUkVFeVowRk5SMVZEVFVNdlJuZzFRbUlLWVdVM1F6ZDNOVU5xZWxCblFVbFNRamh6UVZZMVZFaEdOMFY1YmtocVJuaENjV3AzV1docFRXSnNlVzQxYkhwM2NGUnpVM0JqUjNscFVVbDRRVTEwVUFwQ1FVMWFXR0pLWlZrNFRFd3ZjbFJ0Y25GaFV5dG5kbFZEUmxwbE5ETXdjR1l2TjI1cVlta3JkazFVYzI1WU5teGllVVJYTml0TlFsQm1NbmN3VVQwOUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "+4WhNBSwKMSboYu9UjwtBVowtWsYuSzkVOosUe3GVsQ="}, "signature": "MEUCIQCsK+1qTf4fGwb5y0nhzbAwJkXnpe2t63eOzkukCd9lSQIgCO3QoxnLW6oAr2M20S//y8iDUKEGe3pipLwC/+zmLnA="}} diff --git a/Python-3.12.13.tar.xz b/Python-3.12.13.tar.xz new file mode 100644 index 0000000..e53cbfa --- /dev/null +++ b/Python-3.12.13.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c08bc65a81971c1dd5783182826503369466c7e67374d1646519adf05207b684 +size 20801708 diff --git a/Python-3.12.13.tar.xz.asc b/Python-3.12.13.tar.xz.asc new file mode 100644 index 0000000..9888566 --- /dev/null +++ b/Python-3.12.13.tar.xz.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmmm3hlfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDcx +Njk2MDVGNjJDNzUxMzU2RDA1NEEyNkE4MjFFNjgwRTVGQTYzMDUACgkQqCHmgOX6 +YwW/NA/+MsD99kuy8nBgrK65H3nVj104QcYaau9qhQ62x5+d7P04sVs8bf0mo/AM +zec7eCTHnwoLVborEiqyd5NPRUFNJRfsIn0g4z0PIWRBaXsPztMT4suQdNw+VOTd +3+up8Um0cA2tnesiXZvT5mXY/2kjffcosP/D4OjdADEGYcUawgNeY4LQi9sTOzs6 +ubI+mrtSqlAzgKM5NeVj2LdXPeLhpFz4TPk5GTlp0N9p5I1/7ZjK6eLw9p1gPZNN +xzN84JL191a9DybGJXIEJ6AcN5TxuBwXHV/KlnEK57AGj1WS5VOhKbHGoSwpRU5m +BAtCfJj0zBVqME9W/rROR5mxhta/kG71594STPhXKppyQaH+f41lseNf32So0O+w +PdCVebFJgNnCM8Sl+NMrfqiVKW17bAwk4POtbSVqALq3Y2mseDUr0ggU/ZNgeKHy +bDxPBSWAAI3kE75yZlXrAJYYiEWgc5GMZJQgFqOJfw1nDmfZL626ckyDdsJotiJO +6pZKmFqLlTPkXzw1t45z8/ZI8p/oWrMnTS/IGMcTobXcWHEBvbn9Ljt6nBLrZgO6 +67vTGss5KhjvfyKwNyQGkG+KIoUJLoewFJ6l5okZB5JIALYn1f/P3bl/kJPUDNp4 +eP2ao9kSYBBOwutUe1lH8tQYrNGA0C80hPykvbWDHcvF13J5k2E= +=KNz3 +-----END PGP SIGNATURE----- diff --git a/Python-3.12.13.tar.xz.sigstore b/Python-3.12.13.tar.xz.sigstore new file mode 100644 index 0000000..a51cafb --- /dev/null +++ b/Python-3.12.13.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICyjCCAlGgAwIBAgIUO7TJR+RHchxVU5kgvbim2H9+cbcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwMzAzMTMxMjIwWhcNMjYwMzAzMTMyMjIwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELwC+xgTfcROEXl4pozmTWsTNPZLTeacmkg6Hg0WATZMDJ+lr38EW6hvCs6TDkHrSaW6cdK1cwiJkn1Fll29q/KOCAXAwggFsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUmvaaERiEcY/i892YYr9Mxt7u1pAwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0RAQH/BBUwE4ERdGhvbWFzQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGcs9P79QAABAMASDBGAiEAtjJfOYWsz9g9ZW3xOzvooREK151hFSCpuGGQfA0CoEECIQChliLi08aP9JK7exWp1EUkEsLQ8xS3k6dKzK08r1FK3jAKBggqhkjOPQQDAwNnADBkAjA5RnsbbOv8594Rg66k8ehuGKRy9tuwnGeh+Ms/7QH9azMryf4lq2MWW6gs3oJFeYcCMC/oCuy0KqaSKLjL+Bjkw206Xydj9Wcxzi6n/HeqnxiZrBz790kpkwjsxOJnaUIQyg=="}, "tlogEntries": [{"logIndex": "1017907816", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1772543540", "inclusionPromise": {"signedEntryTimestamp": "MEYCIQDT7wtacuqV+7MUnwBq5Rqq3l63sLEGHZI1XuWp0421qgIhAP1/dl8he7N/t5VMUhca4SFy/Wd1VCYHhB8pvaVeTnG6"}, "inclusionProof": {"logIndex": "896003554", "rootHash": "dduWJQVh9hToIh7KBktgBf1ZmjzxXKBtY6RlC8Qvck8=", "treeSize": "896003562", "hashes": ["c24gaFO/5zpzzLClPoHIHcfL0tXHo4KM0fe1kRP1mXA=", "2TTK3bhgXfKMKbX6Sykzb4FK7KWTGFwZt3cL6RDnrhQ=", "UDmpPuP1lUhqv/P+G1TT3lwHHar8e66rgtFoftcCyFA=", "1cimjEHaKfeVzMwQ2g5aNI2AY+mKuyefuKu4bl3dYYY=", "ov3364KQKY67aOFB2yraPDt2tN2J3ubsoFc0Qz4Uyqc=", "QDY5M9oZY+lj4k8u1dw8TLSPZMx2RaFU6azxmtI/DYk=", "wjOmQYl/uPBoLszh0aCCIaStXoKgMBx2hr8/yd8mrxw=", "SWlkQuEKVKLExEBBYik+E2ntQcWU8FXaStLk5OR58Hw=", "TT/C2pqjIfvIL3alv8+8t803UUA+J7F3G3RJBGX47qo=", "QIvLvG9kOJaMYUH84Qv3nYMwHBgvO09NBWZgAQxV/XQ=", "Xu3Ph++KXQYw4sr2FXO+m6ejdFnRdvIq0sNIXZ3JPeI=", "X/ABFC6+4cGeNLxsbeuvEES5P1gqWZNVz354NrulKvs=", "JRrqNWh/H7qLgers5uYHsZhlBeUG0Iq15/rzmx5nOnM=", "zqeC5oCJfF7U0j+xFOZMczDTNKLpXtPqv1Bm2CRa+q8=", "3MUmJMn+WmTO/xZck3ZnB+/1ODBh1XagFTFyOYA8fGg=", "9kv572LTRu9iSxQwHZ/9IjIVAil7jC0UKQGvJ1+OSIc=", "Qiu5gIc/ZjU7HM63IWVs3PCkgNTV4cY0dnn0aOI66WY=", "TowAI7Ml+oo4i97aYU8IPGwFN1B4qy+pdx75ciLu3E8=", "Xo5tam8gxbsWohATkFEqn5hvHpPFwBJ0SDjNE5DiI2A=", "ZleKYeRKwUF3HP3HO0kxHMVeJgY3N/euGinVhlVWaq0=", "fLAvE46NqCVV86EpB2pKkwJlFjjFk7ntX3lC+PiZuIo=", "T4DqWD42hAtN+vX8jKCWqoC4meE4JekI9LxYGCcPy1M="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n896003562\ndduWJQVh9hToIh7KBktgBf1ZmjzxXKBtY6RlC8Qvck8=\n\n\u2014 rekor.sigstore.dev wNI9ajBEAiBkoWZ7HDLN0R8PyB2wRfwbnaOwvM8cdqelTzCaeOAFzQIgREZTN2XN/tZDjqkuie8cGAVFpOtF05VIsGCgvUZX9+s=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjMDhiYzY1YTgxOTcxYzFkZDU3ODMxODI4MjY1MDMzNjk0NjZjN2U2NzM3NGQxNjQ2NTE5YWRmMDUyMDdiNjg0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURpN3FEa0c3UGQvaEpiYnVCK0MwZlF1bDlUaDlwY253Y2I0QVpnSFY0L09RSWdhVDdqZkg0cWdQbWJOSE5jbzFpMVdWdTUzS3ZBanI1bVBIRGVBcVY5RThvPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjVha05EUVd4SFowRjNTVUpCWjBsVlR6ZFVTbElyVWtoamFIaFdWVFZyWjNaaWFXMHlTRGtyWTJKamQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDE2UVhwTlZFMTRUV3BKZDFkb1kwNU5hbGwzVFhwQmVrMVVUWGxOYWtsM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZNZDBNcmVHZFVabU5TVDBWWWJEUndiM3B0VkZkelZFNVFXa3hVWldGamJXdG5Oa2dLWnpCWFFWUmFUVVJLSzJ4eU16aEZWelpvZGtOek5sUkVhMGh5VTJGWE5tTmtTekZqZDJsS2EyNHhSbXhzTWpseEwwdFBRMEZZUVhkblowWnpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZ0ZG1GaENrVlNhVVZqV1M5cE9Ea3lXVmx5T1UxNGREZDFNWEJCZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoM1dVUldVakJTUVZGSUwwSkNWWGRGTkVWU1pFZG9kbUpYUm5wUlNFSTFaRWRvZG1KcE5YWmpiV04zUzFGWlMwdDNXVUpDUVVkRWRucEJRZ3BCVVZGaVlVaFNNR05JVFRaTWVUbG9XVEpPZG1SWE5UQmplVFZ1WWpJNWJtSkhWWFZaTWpsMFRVTnpSME5wYzBkQlVWRkNaemM0ZDBGUlowVklVWGRpQ21GSVVqQmpTRTAyVEhrNWFGa3lUblprVnpVd1kzazFibUl5T1c1aVIxVjFXVEk1ZEUxSlIweENaMjl5UW1kRlJVRmtXalZCWjFGRFFrZ3dSV1YzUWpVS1FVaGpRVE5VTUhkaGMySklSVlJLYWtkU05HTnRWMk16UVhGS1MxaHlhbVZRU3pNdmFEUndlV2RET0hBM2J6UkJRVUZIWTNNNVVEYzVVVUZCUWtGTlFRcFRSRUpIUVdsRlFYUnFTbVpQV1ZkemVqbG5PVnBYTTNoUGVuWnZiMUpGU3pFMU1XaEdVME53ZFVkSFVXWkJNRU52UlVWRFNWRkRhR3hwVEdrd09HRlFDamxLU3pkbGVGZHdNVVZWYTBWelRGRTRlRk16YXpaa1MzcExNRGh5TVVaTE0ycEJTMEpuWjNGb2EycFBVRkZSUkVGM1RtNUJSRUpyUVdwQk5WSnVjMklLWWs5Mk9EVTVORkpuTmpack9HVm9kVWRMVW5rNWRIVjNia2RsYUN0TmN5ODNVVWc1WVhwTmNubG1OR3h4TWsxWFZ6Wm5jek52U2tabFdXTkRUVU12YndwRGRYa3dTM0ZoVTB0TWFrd3JRbXByZHpJd05saDVaR281VjJONGVtazJiaTlJWlhGdWVHbGFja0o2Tnprd2EzQnJkMnB6ZUU5S2JtRlZTVkY1WnowOUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "wIvGWoGXHB3VeDGCgmUDNpRmx+ZzdNFkZRmt8FIHtoQ="}, "signature": "MEUCIQDi7qDkG7Pd/hJbbuB+C0fQul9Th9pcnwcb4AZgHV4/OQIgaT7jfH4qgPmbNHNco1i1WVu53KvAjr5mPHDeAqV9E8o="}} diff --git a/fix_configure_rst.patch b/fix_configure_rst.patch index 2528ab1..312be1f 100644 --- a/fix_configure_rst.patch +++ b/fix_configure_rst.patch @@ -3,10 +3,10 @@ Misc/NEWS | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) -Index: Python-3.12.12/Doc/using/configure.rst +Index: Python-3.12.13/Doc/using/configure.rst =================================================================== ---- Python-3.12.12.orig/Doc/using/configure.rst 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Doc/using/configure.rst 2025-11-15 16:08:56.030736737 +0100 +--- Python-3.12.13.orig/Doc/using/configure.rst 2026-03-06 20:22:08.230317302 +0100 ++++ Python-3.12.13/Doc/using/configure.rst 2026-03-06 20:22:22.242697945 +0100 @@ -640,13 +640,11 @@ See ``Mac/README.rst``. @@ -21,11 +21,11 @@ Index: Python-3.12.12/Doc/using/configure.rst .. option:: --enable-framework=INSTALLDIR Create a Python.framework rather than a traditional Unix install. Optional -Index: Python-3.12.12/Misc/NEWS +Index: Python-3.12.13/Misc/NEWS =================================================================== ---- Python-3.12.12.orig/Misc/NEWS 2025-10-09 13:07:00.000000000 +0200 -+++ Python-3.12.12/Misc/NEWS 2025-11-15 16:08:56.040736728 +0100 -@@ -15234,7 +15234,7 @@ +--- Python-3.12.13.orig/Misc/NEWS 2026-03-06 20:22:08.230317302 +0100 ++++ Python-3.12.13/Misc/NEWS 2026-03-06 20:22:22.248451941 +0100 +@@ -15317,7 +15317,7 @@ - bpo-40939: Removed documentation for the removed ``PyParser_*`` C API. - bpo-43795: The list in :ref:`limited-api-list` now shows the public name diff --git a/pass-test_write_read_limited_history.patch b/pass-test_write_read_limited_history.patch index 7eadf12..a407c45 100644 --- a/pass-test_write_read_limited_history.patch +++ b/pass-test_write_read_limited_history.patch @@ -1,7 +1,11 @@ -Index: Python-3.12.12/Modules/readline.c +--- + Modules/readline.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +Index: Python-3.12.13/Modules/readline.c =================================================================== ---- Python-3.12.12.orig/Modules/readline.c 2025-11-19 20:17:29.982940492 +0100 -+++ Python-3.12.12/Modules/readline.c 2025-11-19 20:36:46.627307300 +0100 +--- Python-3.12.13.orig/Modules/readline.c 2026-03-03 13:39:30.000000000 +0100 ++++ Python-3.12.13/Modules/readline.c 2026-03-06 20:22:54.135627806 +0100 @@ -145,6 +145,8 @@ #define readlinestate_global ((readlinestate *)PyModule_GetState(PyState_FindModule(&readlinemodule))) diff --git a/python312.changes b/python312.changes index b67b7a6..ff40af9 100644 --- a/python312.changes +++ b/python312.changes @@ -1,3 +1,86 @@ +------------------------------------------------------------------- +Fri Mar 6 19:20:34 UTC 2026 - Matej Cepl + +- Update to 3.12.13: + - Python 3.12.13 final + - Release date: 2026-03-03 + - Security + - gh-144125: BytesGenerator will now refuse to serialize + (write) headers that are unsafely folded or delimited; see + verify_generated_headers. (Contributed by Bas Bloemsaat and + Petr Viktorin in gh-121650). + - gh-143935: Fixed a bug in the folding of comments when + flattening an email message using a modern email policy. + Comments consisting of a very long sequence of non-foldable + characters could trigger a forced line wrap that omitted + the required leading space on the continuation line, + causing the remainder of the comment to be interpreted as + a new header field. This enabled header injection with + carefully crafted inputs (bsc#1257029 CVE-2025-11468). + - gh-143925: Reject control characters in data: URL media + types (bsc#1257046, CVE-2025-15282). + - gh-143919: Reject control characters in http.cookies.Morsel + fields and values (bsc#1257031, CVE-2026-0672). + - gh-143916: Reject C0 control characters within + wsgiref.headers.Headers fields, values, and parameters + (bsc#1257042, CVE-2026-0865). + - gh-142145: Remove quadratic behavior in xml.minidom node ID + cache clearing. In order to do this without breaking + existing users, we also add the ownerDocument attribute to + xml.dom.minidom elements and attributes created by directly + instantiating the Element or Attr class. Note that this way + of creating nodes is not supported; creator functions like + xml.dom.Document.documentElement() should be used instead + (bsc#1254997, CVE-2025-12084). + - gh-137836: Add support of the “plaintext” element, RAWTEXT + elements “xmp”, “iframe”, “noembed” and “noframes”, and + optionally RAWTEXT element “noscript” in + html.parser.HTMLParser. + - gh-136063: email.message: ensure linear complexity for + legacy HTTP parameters parsing. Patch by Bénédikt Tran. + - gh-136065: Fix quadratic complexity in + os.path.expandvars() (bsc#1252974, CVE-2025-6075). + - gh-119451: Fix a potential memory denial of service in the + http.client module. When connecting to a malicious server, + it could cause an arbitrary amount of memory to be + allocated. This could have led to symptoms including + a MemoryError, swapping, out of memory (OOM) killed + processes or containers, or even system crashes + (CVE-2025-13836, bsc#1254400). + - gh-119452: Fix a potential memory denial of service in the + http.server module. When a malicious user is connected to + the CGI server on Windows, it could cause an arbitrary + amount of memory to be allocated. This could have led to + symptoms including a MemoryError, swapping, out of memory + (OOM) killed processes or containers, or even system + crashes. + - gh-119342: Fix a potential memory denial of service in the + plistlib module. When reading a Plist file received from + untrusted source, it could cause an arbitrary amount of + memory to be allocated. This could have led to symptoms + including a MemoryError, swapping, out of memory (OOM) + killed processes or containers, or even system crashes + (bsc#1254401, CVE-2025-13837). + - Library + - gh-144833: Fixed a use-after-free in ssl when SSL_new() + returns NULL in newPySSLSocket(). The error was reported + via a dangling pointer after the object had already been + freed. + - gh-144363: Update bundled libexpat to 2.7.4 + - gh-90949: Add SetAllocTrackerActivationThreshold() and + SetAllocTrackerMaximumAmplification() to xmlparser objects + to prevent use of disproportional amounts of dynamic memory + from within an Expat parser. Patch by Bénédikt Tran. +- Remove upstreamed patches: + - CVE-2025-11468-email-hdr-fold-comment.patch + - CVE-2025-12084-minidom-quad-search.patch + - CVE-2025-13836-http-resp-cont-len.patch + - CVE-2025-13837-plistlib-mailicious-length.patch + - CVE-2025-6075-expandvars-perf-degrad.patch + - CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch + - CVE-2026-0865-wsgiref-ctrl-chars.patch + - CVE-2025-15282-urllib-ctrl-chars.patch + ------------------------------------------------------------------- Fri Feb 6 00:07:20 CET 2026 - Matej Cepl diff --git a/python312.spec b/python312.spec index 17eeef8..cbb1c10 100644 --- a/python312.spec +++ b/python312.spec @@ -118,7 +118,7 @@ # _md5.cpython-38m-x86_64-linux-gnu.so %define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so Name: %{python_pkg_name}%{psuffix} -Version: 3.12.12 +Version: 3.12.13 Release: 0 Summary: Python 3 Interpreter License: Python-2.0