From bdcf742e6cef5483c82e71630e544316a6dfd189 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 24 Aug 2026 16:30:49 -0400 Subject: [PATCH] import UBI python3.12-3.12.14-1.el9_8 --- .gitignore | 2 +- .python3.12.metadata | 2 +- SOURCES/00397-tarfile-filter.patch | 38 ++--- SOURCES/00478-cve-2026-4519.patch | 105 ------------- SOURCES/00479-cve-2026-1502.patch | 107 ------------- SOURCES/00480-cve-2026-4786.patch | 64 -------- SOURCES/00482-cve-2026-6100.patch | 61 -------- SOURCES/00483-cve-2026-2297.patch | 33 ---- SOURCES/00484-cve-2026-3644.patch | 146 ------------------ SOURCES/00485-cve-2026-4224.patch | 98 ------------ SOURCES/00490-cve-2026-15308.patch | 114 -------------- ...-test_large_content_length_truncated.patch | 23 +++ SOURCES/Python-3.12.13.tar.xz.asc | 18 --- SOURCES/Python-3.12.14.tar.xz.asc | 16 ++ SPECS/python3.12.spec | 65 ++------ 15 files changed, 71 insertions(+), 821 deletions(-) delete mode 100644 SOURCES/00478-cve-2026-4519.patch delete mode 100644 SOURCES/00479-cve-2026-1502.patch delete mode 100644 SOURCES/00480-cve-2026-4786.patch delete mode 100644 SOURCES/00482-cve-2026-6100.patch delete mode 100644 SOURCES/00483-cve-2026-2297.patch delete mode 100644 SOURCES/00484-cve-2026-3644.patch delete mode 100644 SOURCES/00485-cve-2026-4224.patch delete mode 100644 SOURCES/00490-cve-2026-15308.patch create mode 100644 SOURCES/00494-increase-the-timeout-of-test_large_content_length_truncated.patch delete mode 100644 SOURCES/Python-3.12.13.tar.xz.asc create mode 100644 SOURCES/Python-3.12.14.tar.xz.asc diff --git a/.gitignore b/.gitignore index e6187d4..69b752f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/Python-3.12.13.tar.xz +SOURCES/Python-3.12.14.tar.xz diff --git a/.python3.12.metadata b/.python3.12.metadata index c716d38..4a897f5 100644 --- a/.python3.12.metadata +++ b/.python3.12.metadata @@ -1 +1 @@ -ad3e9c333d91bee73f1d5f4a6fe6e88f2e74d911 SOURCES/Python-3.12.13.tar.xz +3b3ddf03a7265334f6ed69b4e7a6d77186416135 SOURCES/Python-3.12.14.tar.xz diff --git a/SOURCES/00397-tarfile-filter.patch b/SOURCES/00397-tarfile-filter.patch index 7c87d73..946232e 100644 --- a/SOURCES/00397-tarfile-filter.patch +++ b/SOURCES/00397-tarfile-filter.patch @@ -1,6 +1,6 @@ -From ddd8064257a1916726b784d43f18e889ea1634f7 Mon Sep 17 00:00:00 2001 +From e4f5d016df1811c2f42b33faa197f3295cf2cb61 Mon Sep 17 00:00:00 2001 From: Petr Viktorin -Date: Tue, 2 Jul 2024 11:40:37 +0200 +Date: Thu, 20 Aug 2026 13:03:09 +0200 Subject: [PATCH] CVE-2007-4559, PEP-706: Add filters for tarfile extraction (downstream) MIME-Version: 1.0 @@ -11,14 +11,15 @@ Add and test RHEL-specific ways of configuring the default behavior: environment variable and config file. Co-Authored-By: Tomáš Hrnčiar +Co-Authored-By: Lumír Balhar --- Lib/tarfile.py | 47 +++++++++++-- Lib/test/test_shutil.py | 2 +- - Lib/test/test_tarfile.py | 147 +++++++++++++++++++++++++++++++++++++-- - 3 files changed, 185 insertions(+), 11 deletions(-) + Lib/test/test_tarfile.py | 146 +++++++++++++++++++++++++++++++++++++-- + 3 files changed, 184 insertions(+), 11 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index e1487e3..89b6843 100755 +index 053adc0..386643d 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -71,6 +71,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError", @@ -35,7 +36,7 @@ index e1487e3..89b6843 100755 #--------------------------------------------------------- # tar constants -@@ -2218,11 +2225,41 @@ class TarFile(object): +@@ -2300,11 +2307,41 @@ class TarFile(object): if filter is None: filter = self.extraction_filter if filter is None: @@ -83,10 +84,10 @@ index e1487e3..89b6843 100755 if isinstance(filter, str): raise TypeError( diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py -index 7bc5d12..88b4bdb 100644 +index b7be547..e022392 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py -@@ -2096,7 +2096,7 @@ class TestArchives(BaseTest, unittest.TestCase): +@@ -2089,7 +2089,7 @@ class TestArchives(BaseTest, unittest.TestCase): self.check_unpack_archive(format, filter='fully_trusted') self.check_unpack_archive(format, filter='data') with warnings_helper.check_warnings( @@ -96,10 +97,10 @@ index 7bc5d12..88b4bdb 100644 def test_unpack_archive_tar(self): diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index 3fbd25e..9aa727e 100644 +index 062b366..596c9a9 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py -@@ -727,7 +727,17 @@ class MiscReadTestBase(CommonReadTest): +@@ -728,7 +728,17 @@ class MiscReadTestBase(CommonReadTest): tarfile.open(tarname, encoding="iso8859-1") as tar ): directories = [t for t in tar if t.isdir()] @@ -118,7 +119,7 @@ index 3fbd25e..9aa727e 100644 tar.extractall(DIR, directories) # check that the stacklevel of the deprecation warning is correct: self.assertEqual(cm.filename, __file__) -@@ -740,7 +750,17 @@ class MiscReadTestBase(CommonReadTest): +@@ -741,7 +751,17 @@ class MiscReadTestBase(CommonReadTest): tarfile.open(tarname, encoding="iso8859-1") as tar ): tarinfo = tar.getmember(dirtype) @@ -137,7 +138,7 @@ index 3fbd25e..9aa727e 100644 tar.extract(tarinfo, path=DIR) # check that the stacklevel of the deprecation warning is correct: self.assertEqual(cm.filename, __file__) -@@ -3144,8 +3164,8 @@ class NoneInfoExtractTests(ReadTest): +@@ -3235,8 +3255,8 @@ class NoneInfoExtractTests(ReadTest): tar.errorlevel = 0 with ExitStack() as cm: if cls.extraction_filter is None: @@ -148,7 +149,7 @@ index 3fbd25e..9aa727e 100644 tar.extractall(cls.control_dir, filter=cls.extraction_filter) tar.close() cls.control_paths = set( -@@ -3966,7 +3986,7 @@ class TestExtractionFilters(unittest.TestCase): +@@ -4505,7 +4525,7 @@ class TestExtractionFilters(unittest.TestCase): with ArchiveMaker() as arc: arc.add('foo') with warnings_helper.check_warnings( @@ -157,9 +158,9 @@ index 3fbd25e..9aa727e 100644 with self.check_context(arc.open(), None): self.expect_file('foo') -@@ -4136,6 +4156,123 @@ class TestExtractionFilters(unittest.TestCase): - self.expect_exception(TypeError) # errorlevel is not int - +@@ -4690,6 +4710,122 @@ class TestExtractionFilters(unittest.TestCase): + with self.assertRaises(tarfile.ReadError): + tar.getmembers() + @contextmanager + def rh_config_context(self, config_lines=None): @@ -277,10 +278,9 @@ index 3fbd25e..9aa727e 100644 + ): + self.check_trusted_default(tar, tempdir) + -+ + class OverwriteTests(archiver_tests.OverwriteTests, unittest.TestCase): testdir = os.path.join(TEMPDIR, "testoverwrite") - -- -2.44.0 +2.55.0 diff --git a/SOURCES/00478-cve-2026-4519.patch b/SOURCES/00478-cve-2026-4519.patch deleted file mode 100644 index 8598b76..0000000 --- a/SOURCES/00478-cve-2026-4519.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Pinky -Date: Wed, 25 Mar 2026 01:02:37 +0530 -Subject: 00478: CVE-2026-4519 - -Reject leading dashes in webbrowser URLs (GH-146360) - -(cherry picked from commit 82a24a4442312bdcfc4c799885e8b3e00990f02b) - -Co-authored-by: Seth Michael Larson ---- - Lib/test/test_webbrowser.py | 5 +++++ - Lib/webbrowser.py | 12 ++++++++++++ - .../2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst | 1 + - 3 files changed, 18 insertions(+) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst - -diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py -index 2d695bc883..60f094fd6a 100644 ---- a/Lib/test/test_webbrowser.py -+++ b/Lib/test/test_webbrowser.py -@@ -59,6 +59,11 @@ def test_open(self): - options=[], - arguments=[URL]) - -+ def test_reject_dash_prefixes(self): -+ browser = self.browser_class(name=CMD_NAME) -+ with self.assertRaises(ValueError): -+ browser.open(f"--key=val {URL}") -+ - - class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase): - -diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py -index 13b9e85f9e..0bdb644d7d 100755 ---- a/Lib/webbrowser.py -+++ b/Lib/webbrowser.py -@@ -158,6 +158,12 @@ def open_new(self, url): - def open_new_tab(self, url): - return self.open(url, 2) - -+ @staticmethod -+ def _check_url(url): -+ """Ensures that the URL is safe to pass to subprocesses as a parameter""" -+ if url and url.lstrip().startswith("-"): -+ raise ValueError(f"Invalid URL: {url}") -+ - - class GenericBrowser(BaseBrowser): - """Class for all browsers started with a command -@@ -175,6 +181,7 @@ def __init__(self, name): - - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -+ self._check_url(url) - cmdline = [self.name] + [arg.replace("%s", url) - for arg in self.args] - try: -@@ -195,6 +202,7 @@ def open(self, url, new=0, autoraise=True): - cmdline = [self.name] + [arg.replace("%s", url) - for arg in self.args] - sys.audit("webbrowser.open", url) -+ self._check_url(url) - try: - if sys.platform[:3] == 'win': - p = subprocess.Popen(cmdline) -@@ -260,6 +268,7 @@ def _invoke(self, args, remote, autoraise, url=None): - - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -+ self._check_url(url) - if new == 0: - action = self.remote_action - elif new == 1: -@@ -350,6 +359,7 @@ class Konqueror(BaseBrowser): - - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -+ self._check_url(url) - # XXX Currently I know no way to prevent KFM from opening a new win. - if new == 2: - action = "newTab" -@@ -554,6 +564,7 @@ def register_standard_browsers(): - class WindowsDefault(BaseBrowser): - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -+ self._check_url(url) - try: - os.startfile(url) - except OSError: -@@ -638,6 +649,7 @@ def _name(self, val): - - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -+ self._check_url(url) - if self.name == 'default': - script = 'open location "%s"' % url.replace('"', '%22') # opens in default browser - else: -diff --git a/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst b/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst -new file mode 100644 -index 0000000000..0f27eae99a ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst -@@ -0,0 +1 @@ -+Reject leading dashes in URLs passed to :func:`webbrowser.open` diff --git a/SOURCES/00479-cve-2026-1502.patch b/SOURCES/00479-cve-2026-1502.patch deleted file mode 100644 index 16dc99b..0000000 --- a/SOURCES/00479-cve-2026-1502.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Seth Larson -Date: Fri, 10 Apr 2026 10:21:42 -0500 -Subject: 00479: CVE-2026-1502 - -Reject CR/LF in HTTP tunnel request headers - -Co-authored-by: Illia Volochii ---- - Lib/http/client.py | 11 ++++- - Lib/test/test_httplib.py | 45 +++++++++++++++++++ - ...-03-20-09-29-42.gh-issue-146211.PQVbs7.rst | 2 + - 3 files changed, 57 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst - -diff --git a/Lib/http/client.py b/Lib/http/client.py -index 70451d67d4..7db4807b30 100644 ---- a/Lib/http/client.py -+++ b/Lib/http/client.py -@@ -972,13 +972,22 @@ def _wrap_ipv6(self, ip): - return ip - - def _tunnel(self): -+ if _contains_disallowed_url_pchar_re.search(self._tunnel_host): -+ raise ValueError('Tunnel host can\'t contain control characters %r' -+ % (self._tunnel_host,)) - connect = b"CONNECT %s:%d %s\r\n" % ( - self._wrap_ipv6(self._tunnel_host.encode("idna")), - self._tunnel_port, - self._http_vsn_str.encode("ascii")) - headers = [connect] - for header, value in self._tunnel_headers.items(): -- headers.append(f"{header}: {value}\r\n".encode("latin-1")) -+ header_bytes = header.encode("latin-1") -+ value_bytes = value.encode("latin-1") -+ if not _is_legal_header_name(header_bytes): -+ raise ValueError('Invalid header name %r' % (header_bytes,)) -+ if _is_illegal_header_value(value_bytes): -+ raise ValueError('Invalid header value %r' % (value_bytes,)) -+ headers.append(b"%s: %s\r\n" % (header_bytes, value_bytes)) - headers.append(b"\r\n") - # Making a single send() call instead of one per line encourages - # the host OS to use a more optimal packet size instead of -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py -index e46dac0077..e027d930d9 100644 ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -369,6 +369,51 @@ def test_invalid_headers(self): - with self.assertRaisesRegex(ValueError, 'Invalid header'): - conn.putheader(name, value) - -+ def test_invalid_tunnel_headers(self): -+ cases = ( -+ ('Invalid\r\nName', 'ValidValue'), -+ ('Invalid\rName', 'ValidValue'), -+ ('Invalid\nName', 'ValidValue'), -+ ('\r\nInvalidName', 'ValidValue'), -+ ('\rInvalidName', 'ValidValue'), -+ ('\nInvalidName', 'ValidValue'), -+ (' InvalidName', 'ValidValue'), -+ ('\tInvalidName', 'ValidValue'), -+ ('Invalid:Name', 'ValidValue'), -+ (':InvalidName', 'ValidValue'), -+ ('ValidName', 'Invalid\r\nValue'), -+ ('ValidName', 'Invalid\rValue'), -+ ('ValidName', 'Invalid\nValue'), -+ ('ValidName', 'InvalidValue\r\n'), -+ ('ValidName', 'InvalidValue\r'), -+ ('ValidName', 'InvalidValue\n'), -+ ) -+ for name, value in cases: -+ with self.subTest((name, value)): -+ conn = client.HTTPConnection('example.com') -+ conn.set_tunnel('tunnel', headers={ -+ name: value -+ }) -+ conn.sock = FakeSocket('') -+ with self.assertRaisesRegex(ValueError, 'Invalid header'): -+ conn._tunnel() # Called in .connect() -+ -+ def test_invalid_tunnel_host(self): -+ cases = ( -+ 'invalid\r.host', -+ '\ninvalid.host', -+ 'invalid.host\r\n', -+ 'invalid.host\x00', -+ 'invalid host', -+ ) -+ for tunnel_host in cases: -+ with self.subTest(tunnel_host): -+ conn = client.HTTPConnection('example.com') -+ conn.set_tunnel(tunnel_host) -+ conn.sock = FakeSocket('') -+ with self.assertRaisesRegex(ValueError, 'Tunnel host can\'t contain control characters'): -+ conn._tunnel() # Called in .connect() -+ - def test_headers_debuglevel(self): - body = ( - b'HTTP/1.1 200 OK\r\n' -diff --git a/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst -new file mode 100644 -index 0000000000..4993633b8e ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst -@@ -0,0 +1,2 @@ -+Reject CR/LF characters in tunnel request headers for the -+HTTPConnection.set_tunnel() method. diff --git a/SOURCES/00480-cve-2026-4786.patch b/SOURCES/00480-cve-2026-4786.patch deleted file mode 100644 index 73e4e13..0000000 --- a/SOURCES/00480-cve-2026-4786.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stan Ulbrych -Date: Mon, 13 Apr 2026 20:02:52 +0100 -Subject: 00480: CVE-2026-4786 - -Fix webbrowser `%action` substitution bypass of dash-prefix check ---- - Lib/test/test_webbrowser.py | 9 +++++++++ - Lib/webbrowser.py | 5 +++-- - .../2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst | 2 ++ - 3 files changed, 14 insertions(+), 2 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst - -diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py -index 60f094fd6a..e900c0212b 100644 ---- a/Lib/test/test_webbrowser.py -+++ b/Lib/test/test_webbrowser.py -@@ -99,6 +99,15 @@ def test_open_new_tab(self): - options=[], - arguments=[URL]) - -+ def test_reject_action_dash_prefixes(self): -+ browser = self.browser_class(name=CMD_NAME) -+ with self.assertRaises(ValueError): -+ browser.open('%action--incognito') -+ # new=1: action is "--new-window", so "%action" itself expands to -+ # a dash-prefixed flag even with no dash in the original URL. -+ with self.assertRaises(ValueError): -+ browser.open('%action', new=1) -+ - - class EdgeCommandTest(CommandTestMixin, unittest.TestCase): - -diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py -index 0bdb644d7d..79d410bcae 100755 ---- a/Lib/webbrowser.py -+++ b/Lib/webbrowser.py -@@ -268,7 +268,6 @@ def _invoke(self, args, remote, autoraise, url=None): - - def open(self, url, new=0, autoraise=True): - sys.audit("webbrowser.open", url) -- self._check_url(url) - if new == 0: - action = self.remote_action - elif new == 1: -@@ -282,7 +281,9 @@ def open(self, url, new=0, autoraise=True): - raise Error("Bad 'new' parameter to open(); " + - "expected 0, 1, or 2, got %s" % new) - -- args = [arg.replace("%s", url).replace("%action", action) -+ self._check_url(url.replace("%action", action)) -+ -+ args = [arg.replace("%action", action).replace("%s", url) - for arg in self.remote_args] - args = [arg for arg in args if arg] - success = self._invoke(args, True, autoraise, url) -diff --git a/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst -new file mode 100644 -index 0000000000..45cdeebe1b ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst -@@ -0,0 +1,2 @@ -+A bypass in :mod:`webbrowser` allowed URLs prefixed with ``%action`` to pass -+the dash-prefix safety check. diff --git a/SOURCES/00482-cve-2026-6100.patch b/SOURCES/00482-cve-2026-6100.patch deleted file mode 100644 index 5656e3d..0000000 --- a/SOURCES/00482-cve-2026-6100.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stan Ulbrych -Date: Mon, 13 Apr 2026 02:14:54 +0100 -Subject: 00482: CVE-2026-6100 - -Fix a possible UAF in {LZMA,BZ2,_Zlib}Decompressor ---- - .../Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst | 5 +++++ - Modules/_bz2module.c | 1 + - Modules/_lzmamodule.c | 1 + - Modules/zlibmodule.c | 1 + - 4 files changed, 8 insertions(+) - create mode 100644 Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst - -diff --git a/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst -new file mode 100644 -index 0000000000..9502189ab1 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst -@@ -0,0 +1,5 @@ -+Fix a dangling input pointer in :class:`lzma.LZMADecompressor`, -+:class:`bz2.BZ2Decompressor`, and internal :class:`!zlib._ZlibDecompressor` -+when memory allocation fails with :exc:`MemoryError`, which could let a -+subsequent :meth:`!decompress` call read or write through a stale pointer to -+the already-released caller buffer. -diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c -index 97bd44b4ac..a732e89d55 100644 ---- a/Modules/_bz2module.c -+++ b/Modules/_bz2module.c -@@ -587,6 +587,7 @@ decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) - return result; - - error: -+ bzs->next_in = NULL; - Py_XDECREF(result); - return NULL; - } -diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c -index 7bbd6569aa..103a6ef86c 100644 ---- a/Modules/_lzmamodule.c -+++ b/Modules/_lzmamodule.c -@@ -1114,6 +1114,7 @@ decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) - return result; - - error: -+ lzs->next_in = NULL; - Py_XDECREF(result); - return NULL; - } -diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c -index f94c57e4c8..9759593b6a 100644 ---- a/Modules/zlibmodule.c -+++ b/Modules/zlibmodule.c -@@ -1645,6 +1645,7 @@ decompress(ZlibDecompressor *self, uint8_t *data, - return result; - - error: -+ self->zst.next_in = NULL; - Py_XDECREF(result); - return NULL; - } diff --git a/SOURCES/00483-cve-2026-2297.patch b/SOURCES/00483-cve-2026-2297.patch deleted file mode 100644 index 8b504c9..0000000 --- a/SOURCES/00483-cve-2026-2297.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Dower -Date: Wed, 4 Mar 2026 19:55:52 +0000 -Subject: 00483: CVE-2026-2297 - -Logging Bypass in Legacy .pyc File Handling ---- - Lib/importlib/_bootstrap_external.py | 2 +- - .../Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst - -diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py -index 9b8a8dfc5a..6e4a087a10 100644 ---- a/Lib/importlib/_bootstrap_external.py -+++ b/Lib/importlib/_bootstrap_external.py -@@ -1186,7 +1186,7 @@ def get_filename(self, fullname): - - def get_data(self, path): - """Return the data from path as raw bytes.""" -- if isinstance(self, (SourceLoader, ExtensionFileLoader)): -+ if isinstance(self, (SourceLoader, SourcelessFileLoader, ExtensionFileLoader)): - with _io.open_code(str(path)) as file: - return file.read() - else: -diff --git a/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst -new file mode 100644 -index 0000000000..dcdb44d4fa ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst -@@ -0,0 +1,2 @@ -+Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses -+:func:`io.open_code` when opening ``.pyc`` files. diff --git a/SOURCES/00484-cve-2026-3644.patch b/SOURCES/00484-cve-2026-3644.patch deleted file mode 100644 index a1c12bd..0000000 --- a/SOURCES/00484-cve-2026-3644.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> -Date: Mon, 16 Mar 2026 13:43:43 +0000 -Subject: 00484: CVE-2026-3644 - -Incomplete control character validation in http.cookies - -Co-authored-by: Victor Stinner ---- - Lib/http/cookies.py | 24 ++++++++++-- - Lib/test/test_http_cookies.py | 38 +++++++++++++++++++ - ...-03-06-17-03-38.gh-issue-145599.kchwZV.rst | 4 ++ - 3 files changed, 62 insertions(+), 4 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst - -diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py -index d0a69cbe19..63d119ad46 100644 ---- a/Lib/http/cookies.py -+++ b/Lib/http/cookies.py -@@ -335,9 +335,16 @@ def update(self, values): - 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 " -+ f"cookies {key!r} {val!r}") - data[key] = val - dict.update(self, data) - -+ def __ior__(self, values): -+ self.update(values) -+ return self -+ - def isReservedKey(self, K): - return K.lower() in self._reserved - -@@ -363,9 +370,15 @@ def __getstate__(self): - } - - def __setstate__(self, state): -- self._key = state['key'] -- self._value = state['value'] -- self._coded_value = state['coded_value'] -+ key = state['key'] -+ value = state['value'] -+ coded_value = state['coded_value'] -+ if _has_control_character(key, value, coded_value): -+ raise CookieError("Control characters are not allowed in cookies " -+ f"{key!r} {value!r} {coded_value!r}") -+ self._key = key -+ self._value = value -+ self._coded_value = coded_value - - def output(self, attrs=None, header="Set-Cookie:"): - return "%s %s" % (header, self.OutputString(attrs)) -@@ -377,13 +390,16 @@ def __repr__(self): - - def js_output(self, attrs=None): - # Print javascript -+ output_string = self.OutputString(attrs) -+ if _has_control_character(output_string): -+ raise CookieError("Control characters are not allowed in cookies") - return """ - -- """ % (self.OutputString(attrs).replace('"', r'\"')) -+ """ % (output_string.replace('"', r'\"')) - - def OutputString(self, attrs=None): - # Build up our result -diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py -index f196bcc48e..2478a6c630 100644 ---- a/Lib/test/test_http_cookies.py -+++ b/Lib/test/test_http_cookies.py -@@ -573,6 +573,14 @@ def test_control_characters(self): - with self.assertRaises(cookies.CookieError): - morsel["path"] = c0 - -+ # .__setstate__() -+ with self.assertRaises(cookies.CookieError): -+ morsel.__setstate__({'key': c0, 'value': 'val', 'coded_value': 'coded'}) -+ with self.assertRaises(cookies.CookieError): -+ morsel.__setstate__({'key': 'key', 'value': c0, 'coded_value': 'coded'}) -+ with self.assertRaises(cookies.CookieError): -+ morsel.__setstate__({'key': 'key', 'value': 'val', 'coded_value': c0}) -+ - # .setdefault() - with self.assertRaises(cookies.CookieError): - morsel.setdefault("path", c0) -@@ -587,6 +595,18 @@ def test_control_characters(self): - with self.assertRaises(cookies.CookieError): - morsel.set("path", "val", c0) - -+ # .update() -+ with self.assertRaises(cookies.CookieError): -+ morsel.update({"path": c0}) -+ with self.assertRaises(cookies.CookieError): -+ morsel.update({c0: "val"}) -+ -+ # .__ior__() -+ with self.assertRaises(cookies.CookieError): -+ morsel |= {"path": c0} -+ with self.assertRaises(cookies.CookieError): -+ morsel |= {c0: "val"} -+ - 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. -@@ -607,6 +627,24 @@ def test_control_characters_output(self): - with self.assertRaises(cookies.CookieError): - cookie.output() - -+ # Tests that .js_output() also 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.js_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.js_output() -+ - - def load_tests(loader, tests, pattern): - tests.addTest(doctest.DocTestSuite(cookies)) -diff --git a/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst b/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst -new file mode 100644 -index 0000000000..e53a932d12 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst -@@ -0,0 +1,4 @@ -+Reject control characters in :class:`http.cookies.Morsel` -+:meth:`~http.cookies.Morsel.update` and -+:meth:`~http.cookies.BaseCookie.js_output`. -+This addresses :cve:`2026-3644`. diff --git a/SOURCES/00485-cve-2026-4224.patch b/SOURCES/00485-cve-2026-4224.patch deleted file mode 100644 index 14f8734..0000000 --- a/SOURCES/00485-cve-2026-4224.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> -Date: Sun, 15 Mar 2026 21:46:06 +0000 -Subject: 00485: CVE-2026-4224 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Stack overflow parsing XML with deeply nested DTD content models - -Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> ---- - Lib/test/test_pyexpat.py | 18 ++++++++++++++++++ - ...6-03-14-17-31-39.gh-issue-145986.ifSSr8.rst | 4 ++++ - Modules/pyexpat.c | 9 ++++++++- - 3 files changed, 30 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst - -diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py -index 38f951573f..37d9086f40 100644 ---- a/Lib/test/test_pyexpat.py -+++ b/Lib/test/test_pyexpat.py -@@ -675,6 +675,24 @@ def test_change_size_2(self): - parser.Parse(xml2, True) - self.assertEqual(self.n, 4) - -+class ElementDeclHandlerTest(unittest.TestCase): -+ def test_deeply_nested_content_model(self): -+ # This should raise a RecursionError and not crash. -+ # See https://github.com/python/cpython/issues/145986. -+ N = 500_000 -+ data = ( -+ b'\n]>\n\n' -+ ) -+ -+ parser = expat.ParserCreate() -+ parser.ElementDeclHandler = lambda _1, _2: None -+ with support.infinite_recursion(): -+ with self.assertRaises(RecursionError): -+ parser.Parse(data) -+ -+ - class MalformedInputTest(unittest.TestCase): - def test1(self): - xml = b"\0\r\n" -diff --git a/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst b/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst -new file mode 100644 -index 0000000000..79536d1fef ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst -@@ -0,0 +1,4 @@ -+:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when -+converting deeply nested XML content models with -+:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`. -+This addresses :cve:`2026-4224`. -diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c -index 79492ca5c4..8673540f35 100644 ---- a/Modules/pyexpat.c -+++ b/Modules/pyexpat.c -@@ -3,6 +3,7 @@ - #endif - - #include "Python.h" -+#include "pycore_ceval.h" // _Py_EnterRecursiveCall() - #include "pycore_runtime.h" // _Py_ID() - #include - -@@ -578,6 +579,10 @@ static PyObject * - conv_content_model(XML_Content * const model, - PyObject *(*conv_string)(const XML_Char *)) - { -+ if (_Py_EnterRecursiveCall(" in conv_content_model")) { -+ return NULL; -+ } -+ - PyObject *result = NULL; - PyObject *children = PyTuple_New(model->numchildren); - int i; -@@ -589,7 +594,7 @@ conv_content_model(XML_Content * const model, - conv_string); - if (child == NULL) { - Py_XDECREF(children); -- return NULL; -+ goto done; - } - PyTuple_SET_ITEM(children, i, child); - } -@@ -597,6 +602,8 @@ conv_content_model(XML_Content * const model, - model->type, model->quant, - conv_string,model->name, children); - } -+done: -+ _Py_LeaveRecursiveCall(); - return result; - } - diff --git a/SOURCES/00490-cve-2026-15308.patch b/SOURCES/00490-cve-2026-15308.patch deleted file mode 100644 index 5341c89..0000000 --- a/SOURCES/00490-cve-2026-15308.patch +++ /dev/null @@ -1,114 +0,0 @@ -From effae3f6f868409068cc0b7ab16fe8e4251352be Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -Date: Sat, 4 Jul 2026 20:40:22 +0300 -Subject: [PATCH] gh-153030: Fix quadratic complexity in incremental parsing in - HTMLParser (GH-153031) - -When an unterminated construct (e.g. a tag or comment) spanned many -feed() calls, rescanning the growing buffer and concatenating new data -onto it were both quadratic. New data is now accumulated in a list and -only joined and parsed once enough has piled up. -(cherry picked from commit bcf98ddbc40ec9b3ee87da0124a5660b19b7e606) - -Co-authored-by: Serhiy Storchaka -Co-Authored-By: Claude Opus 4.8 ---- - Lib/html/parser.py | 32 +++++++++++++++++-- - Lib/test/test_htmlparser.py | 20 ++++++++++++ - ...-07-04-17-00-00.gh-issue-153030.RovkP6.rst | 3 ++ - 3 files changed, 53 insertions(+), 2 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst - -diff --git a/Lib/html/parser.py b/Lib/html/parser.py -index bfab3e64cd54027..c5d2340b712cd6c 100644 ---- a/Lib/html/parser.py -+++ b/Lib/html/parser.py -@@ -138,6 +138,9 @@ def reset(self): - self.cdata_elem = None - self._support_cdata = True - self._escapable = True -+ self._pending = [] -+ self._pending_len = 0 -+ self._parse_threshold = 1 - super().reset() - - def feed(self, data): -@@ -146,11 +149,36 @@ def feed(self, data): - Call this as often as you want, with as little or as much text - as you want (may include '\n'). - """ -- self.rawdata = self.rawdata + data -- self.goahead(0) -+ # Accumulate new data in a list and only join and parse it once -+ # enough has piled up. Rescanning an unparsed buffer (e.g. an -+ # unterminated tag) and concatenating onto it on every call would -+ # both be quadratic in the input size. -+ self._pending_len += len(data) -+ if self._pending_len < self._parse_threshold: -+ self._pending.append(data) -+ else: -+ if not self._pending: -+ self.rawdata += data -+ else: -+ self._pending.append(data) -+ self.rawdata += ''.join(self._pending) -+ self._pending.clear() -+ self._pending_len = 0 -+ n = len(self.rawdata) -+ self.goahead(0) -+ if len(self.rawdata) < n: -+ # Some data was parsed; resume on the next call. -+ self._parse_threshold = 1 -+ else: -+ # Nothing was parsed; wait until the buffer doubles. -+ self._parse_threshold = len(self.rawdata) - - def close(self): - """Handle any buffered data.""" -+ if self._pending: -+ self.rawdata += ''.join(self._pending) -+ self._pending.clear() -+ self._pending_len = 0 - self.goahead(1) - - __starttag_text = None -diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py -index 303c0baa87b026b..e6d92a7ec5166b7 100644 ---- a/Lib/test/test_htmlparser.py -+++ b/Lib/test/test_htmlparser.py -@@ -930,6 +930,26 @@ def check(source): - check("") # comment -+ check("") # processing instruction -+ check("") # doctype -+ check("") # CDATA section -+ check("") # start tag -+ check("") # RAWTEXT element -+ - - class AttributesTestCase(TestCaseBase): - -diff --git a/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst b/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst -new file mode 100644 -index 000000000000000..d1d60593f4ba7d2 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst -@@ -0,0 +1,3 @@ -+Fixed quadratic complexity in incremental parsing of long unterminated -+constructs (such as tags or comments) in :class:`html.parser.HTMLParser`, -+which could be exploited for a denial of service. diff --git a/SOURCES/00494-increase-the-timeout-of-test_large_content_length_truncated.patch b/SOURCES/00494-increase-the-timeout-of-test_large_content_length_truncated.patch new file mode 100644 index 0000000..9d0ef51 --- /dev/null +++ b/SOURCES/00494-increase-the-timeout-of-test_large_content_length_truncated.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Karolina Surma +Date: Fri, 14 Aug 2026 09:38:26 +0200 +Subject: 00494: Increase the timeout of test_large_content_length_truncated + +It has started to fail randomly when run on s390x architecture. +--- + Lib/test/test_httpservers.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py +index 96fc9ca574..6a3f5731a4 100644 +--- a/Lib/test/test_httpservers.py ++++ b/Lib/test/test_httpservers.py +@@ -907,7 +907,7 @@ def test_large_content_length(self): + self.assertEqual(res.read(), b'%d %d' % (size, size) + self.linesep) + + def test_large_content_length_truncated(self): +- with support.swap_attr(self.request_handler, 'timeout', 0.001): ++ with support.swap_attr(self.request_handler, 'timeout', support.LOOPBACK_TIMEOUT): + for w in range(18, 65): + size = 1 << w + headers = {'Content-Length' : str(size)} diff --git a/SOURCES/Python-3.12.13.tar.xz.asc b/SOURCES/Python-3.12.13.tar.xz.asc deleted file mode 100644 index 31701e1..0000000 --- a/SOURCES/Python-3.12.13.tar.xz.asc +++ /dev/null @@ -1,18 +0,0 @@ ------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/SOURCES/Python-3.12.14.tar.xz.asc b/SOURCES/Python-3.12.14.tar.xz.asc new file mode 100644 index 0000000..f4461ee --- /dev/null +++ b/SOURCES/Python-3.12.14.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmp856AACgkQqCHmgOX6 +YwX3/RAAlC9tVv/pADKU55xSVGsLfdVhDQe36MQzEDY/wazSyf8hLnFPx1GpxTFh +bktr/PgPzl60nlT2topPFSCRj9Dh3R41Su1r2c7BF3tPM1qckJ0YxAJ4lqrRozD2 +IFkzLG02fc33skeqBntvi6YQtoLGmCvbbgv0A7R2rtBavSDcduU3L2e2dEeR1Jcu +TfGwSuRXvDFVGDEaPaebhZHnY3Gn/67ZBy5vBrFTfr3vNSq6NsNpX5e/rXietr/B +ITDXeYDqTbWxklrATtUwJAWAxk8jSir7N4Wq2BaQ19WHbYB3seZKmpqQKUGR/E2i +uvFTer1NDIA+lzUZ0EjvasPsiw9JDdVa62I10rnak2WwRbm5BBU3omNv/+8/of1O +kpeuOKbgEWDsoEQC/XTFMPgvf/FUgb/dZEmruLYQw5q61iwhJBmDKE9EpkJtMmgp +08jd7EBUiLdBdLLlbbrf+VyNiUyTEfIr6HJksyGvEYOyDr/UYa+bkz8TApzDmTeG +qXYxwm2mGWE7QKFnz8gsNJspYt+cs+7bNOh84qr1/Q2PSa6qu8V7J6WGVisDvXw7 +vwCwgVxWBcFKr78wNMGbzLxapfb2icmvWZAvFddiEFg2cIVlEPGQ73fiO2bnlOPJ +S6U8Y0O5qNVkLAvp+Kvjcttmn3KIMfl40ZEa85xAY8TJETMXROw= +=JqpT +-----END PGP SIGNATURE----- diff --git a/SPECS/python3.12.spec b/SPECS/python3.12.spec index c5f3aec..4a89d1a 100644 --- a/SPECS/python3.12.spec +++ b/SPECS/python3.12.spec @@ -16,11 +16,11 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well -%global general_version %{pybasever}.13 +%global general_version %{pybasever}.14 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist}.1 +Release: 1%{?dist} License: Python-2.0.1 @@ -418,58 +418,11 @@ Patch474: 00474-cve-2025-15366.patch # (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) Patch475: 00475-cve-2025-15367.patch -# 00478 # eb93352dc8e31f4d52546b84daad875e6ff7f29e -# CVE-2026-4519 +# 00494 # 430aab133397ed44cc9ee621fd311e02fee317b5 +# Increase the timeout of test_large_content_length_truncated # -# Reject leading dashes in webbrowser URLs (GH-146360) -Patch478: 00478-cve-2026-4519.patch - -# 00479 # 97404b2cf62e545c2d41be7ccfed4e74da9ee665 -# CVE-2026-1502 -# -# Reject CR/LF in HTTP tunnel request headers -Patch479: 00479-cve-2026-1502.patch - -# 00480 # 6f4eef3ba4d9818a53698e994550ee8db17a1e2e -# CVE-2026-4786 -# -# Fix webbrowser `%%action` substitution bypass of dash-prefix check -Patch480: 00480-cve-2026-4786.patch - -# 00482 # 69f14bc306fc62400d45565faa980b77858b9151 -# CVE-2026-6100 -# -# Fix a possible UAF in {LZMA,BZ2,_Zlib}Decompressor -Patch482: 00482-cve-2026-6100.patch - -# 00483 # 577c595137ce6ff92158ddaf2d7b7ea86437825d -# CVE-2026-2297 -# -# Logging Bypass in Legacy .pyc File Handling -Patch483: 00483-cve-2026-2297.patch - -# 00484 # 8b5133c1ab17a060cd134bea2a4b6e1831c47fed -# CVE-2026-3644 -# -# Incomplete control character validation in http.cookies -Patch484: 00484-cve-2026-3644.patch - -# 00485 # 12a5b206676927bcee131ab4f2bd6783d2f5914a -# CVE-2026-4224 -# -# Stack overflow parsing XML with deeply nested DTD content models -Patch485: 00485-cve-2026-4224.patch - -# 00490 # -# CVE-2026-15308 -# -# gh-153030: Fix quadratic complexity in incremental parsing in HTMLParser (GH-153031) (GH-153038) -# -# When an unterminated construct (e.g. a tag or comment) spanned many -# feed() calls, rescanning the growing buffer and concatenating new data -# onto it were both quadratic. New data is now accumulated in a list and -# only joined and parsed once enough has piled up. -Patch490: 00490-cve-2026-15308.patch +# It has started to fail randomly when run on s390x architecture. +Patch494: 00494-increase-the-timeout-of-test_large_content_length_truncated.patch # (New patches go here ^^^) # @@ -1789,9 +1742,13 @@ CheckPython optimized # ====================================================== %changelog +* Thu Aug 13 2026 Karolina Surma - 3.12.14-1 +- Update to Python 3.12.14 +Resolves: RHEL-227215 + * Fri Jul 10 2026 Lukáš Zachar - 3.12.13-3.1 - Security fix for CVE-2026-15308 -Resolves: RHEL-RHEL-193793 +Resolves: RHEL-193793 * Mon Jun 01 2026 Lukáš Zachar - 3.12.13-3 - Depend on sqlite-libs with (de)serialize API