Compare commits

...

3 Commits
c9 ... c10s

Author SHA1 Message Date
Charalampos Stratakis
7b3248d1cd Fixup for CVE-2026-6019
Related: RHEL-176147
2026-06-09 17:39:48 +02:00
Miro Hrončok
87a6dd2b48 Update to 3.14.5
Patch 481 merged upstream

(cherry picked from Fedora commit fc230a4cf121ce0218e4f307790abe727664c21f)

Resolves: RHEL-176147
2026-06-09 17:39:02 +02:00
Charalampos Stratakis
2066728bf4 Update to 3.14.5rc1
Move back to the generational from the incremental garbage collector

Security fix for CVE-2026-6019

Patches 479, 480, 482 merged upstream.

(cherry picked from Fedora commit b04f319cc685fc8d26243b3293ad8915fb1a5451)

Resolves: RHEL-176147
2026-06-09 17:37:16 +02:00
9 changed files with 151 additions and 858 deletions

View File

@ -41,7 +41,7 @@ index 5c10bcedc6..1fd7a273b5 100644
result = BytesIO() result = BytesIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 0b343cc4bb..145ecacd21 100644 index 1bd0fde844..f87134c11e 100644
--- a/Lib/test/test_xml_etree.py --- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py
@@ -1573,9 +1573,13 @@ def test_simple_xml(self, chunk_size=None, flush=False): @@ -1573,9 +1573,13 @@ def test_simple_xml(self, chunk_size=None, flush=False):

View File

@ -81,10 +81,10 @@ index 2a17c891dd..64017c666c 100644
} }
#endif #endif
diff --git a/Makefile.pre.in b/Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in
index 80a1b590c2..f28f562930 100644 index da6d7c3315..92a6825b5e 100644
--- a/Makefile.pre.in --- a/Makefile.pre.in
+++ b/Makefile.pre.in +++ b/Makefile.pre.in
@@ -3415,3 +3415,6 @@ MODULE__MULTIBYTECODEC_DEPS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h @@ -3420,3 +3420,6 @@ MODULE__MULTIBYTECODEC_DEPS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h
# Local Variables: # Local Variables:
# mode: makefile # mode: makefile
# End: # End:

View File

@ -1,107 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Seth Larson <seth@python.org>
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 <illia.volochii@gmail.com>
---
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 77f8d26291..6fb7d254ea 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 bcb828edec..6f3eac6b98 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.

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stan Ulbrych <stan@python.org>
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 404b3a31a5..bfbcf112b0 100644
--- a/Lib/test/test_webbrowser.py
+++ b/Lib/test/test_webbrowser.py
@@ -119,6 +119,15 @@ def test_open_bad_new_parameter(self):
arguments=[URL],
kw=dict(new=999))
+ 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 0e0b5034e5..97aad6eea5 100644
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -274,7 +274,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:
@@ -288,7 +287,9 @@ def open(self, url, new=0, autoraise=True):
raise Error("Bad 'new' parameter to open(); "
f"expected 0, 1, or 2, got {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.

View File

@ -1,587 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pablo Galindo Salgado <Pablogsal@gmail.com>
Date: Mon, 13 Apr 2026 23:22:23 +0100
Subject: 00481: CVE-2026-5713
Validate remote debug offset tables on load
---
...-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst | 2 +
Modules/_remote_debugging_module.c | 509 +++++++++++++++++-
2 files changed, 505 insertions(+), 6 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
diff --git a/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
new file mode 100644
index 0000000000..ed138a54a8
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
@@ -0,0 +1,2 @@
+Hardened :mod:`!_remote_debugging` by validating remote debug offset tables
+before using them to size memory reads or interpret remote layouts.
diff --git a/Modules/_remote_debugging_module.c b/Modules/_remote_debugging_module.c
index a327772258..d756ac326f 100644
--- a/Modules/_remote_debugging_module.c
+++ b/Modules/_remote_debugging_module.c
@@ -20,6 +20,7 @@
#include <internal/pycore_interpframe.h> // FRAME_OWNED_BY_CSTACK
#include <internal/pycore_llist.h> // struct llist_node
#include <internal/pycore_stackref.h> // Py_TAG_BITS
+#include <internal/pycore_tstate.h> // _PyThreadStateImpl
#include "../Python/remote_debug.h"
// gh-141784: Python.h header must be included first, before system headers.
@@ -41,9 +42,11 @@
* TYPE DEFINITIONS AND STRUCTURES
* ============================================================================ */
-#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset)))
+#define GET_MEMBER(type, obj, offset) \
+ (*(type *)memcpy(&(type){0}, (const char *)(obj) + (offset), sizeof(type)))
#define CLEAR_PTR_TAG(ptr) (((uintptr_t)(ptr) & ~Py_TAG_BITS))
-#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset))))
+#define GET_MEMBER_NO_TAG(type, obj, offset) \
+ (type)(CLEAR_PTR_TAG(GET_MEMBER(type, obj, offset)))
/* Size macros for opaque buffers */
#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
@@ -107,6 +110,486 @@ struct _Py_AsyncioModuleDebugOffsets {
} asyncio_thread_state;
};
+/* Treat the remote debug tables as untrusted input and validate every
+ * size/offset we later dereference against a fixed local buffer or object
+ * layout before the unwinder starts using them. */
+#define FIELD_SIZE(type, member) sizeof(((type *)0)->member)
+#define PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS (-2)
+
+static inline int
+validate_section_size(const char *section_name, uint64_t size)
+{
+ if (size == 0) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "Invalid debug offsets: %s.size must be greater than zero",
+ section_name);
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+validate_read_size(const char *section_name, uint64_t size, size_t buffer_size)
+{
+ if (validate_section_size(section_name, size) < 0) {
+ return -1;
+ }
+ if (size > buffer_size) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "Invalid debug offsets: %s.size=%llu exceeds local buffer size %zu",
+ section_name,
+ (unsigned long long)size,
+ buffer_size);
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+validate_span(
+ const char *field_name,
+ uint64_t offset,
+ size_t width,
+ uint64_t limit,
+ const char *limit_name)
+{
+ uint64_t span = (uint64_t)width;
+ if (span > limit || offset > limit - span) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "Invalid debug offsets: %s=%llu with width %zu exceeds %s %llu",
+ field_name,
+ (unsigned long long)offset,
+ width,
+ limit_name,
+ (unsigned long long)limit);
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+validate_alignment(
+ const char *field_name,
+ uint64_t offset,
+ size_t alignment)
+{
+ if (alignment > 1 && offset % alignment != 0) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "Invalid debug offsets: %s=%llu is not aligned to %zu bytes",
+ field_name,
+ (unsigned long long)offset,
+ alignment);
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+validate_field(
+ const char *field_name,
+ uint64_t offset,
+ uint64_t reported_size,
+ size_t width,
+ size_t alignment,
+ size_t buffer_size)
+{
+ if (validate_alignment(field_name, offset, alignment) < 0) {
+ return -1;
+ }
+ if (validate_span(field_name, offset, width, reported_size, "reported size") < 0) {
+ return -1;
+ }
+ return validate_span(field_name, offset, width, buffer_size, "local buffer size");
+}
+
+static inline int
+validate_fixed_field(
+ const char *field_name,
+ uint64_t offset,
+ size_t width,
+ size_t alignment,
+ size_t buffer_size)
+{
+ if (validate_alignment(field_name, offset, alignment) < 0) {
+ return -1;
+ }
+ return validate_span(field_name, offset, width, buffer_size, "local buffer size");
+}
+
+#define PY_REMOTE_DEBUG_VALIDATE_SECTION(section) \
+ do { \
+ if (validate_section_size(#section, debug_offsets->section.size) < 0) { \
+ return -1; \
+ } \
+ } while (0)
+
+#define PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(section, buffer_size) \
+ do { \
+ if (validate_read_size(#section, debug_offsets->section.size, buffer_size) < 0) { \
+ return -1; \
+ } \
+ } while (0)
+
+#define PY_REMOTE_DEBUG_VALIDATE_FIELD(section, field, field_size, field_alignment, buffer_size) \
+ do { \
+ if (validate_field( \
+ #section "." #field, \
+ debug_offsets->section.field, \
+ debug_offsets->section.size, \
+ field_size, \
+ field_alignment, \
+ buffer_size) < 0) { \
+ return -1; \
+ } \
+ } while (0)
+
+#define PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(section, field, field_size, field_alignment, buffer_size) \
+ do { \
+ if (validate_fixed_field( \
+ #section "." #field, \
+ debug_offsets->section.field, \
+ field_size, \
+ field_alignment, \
+ buffer_size) < 0) { \
+ return -1; \
+ } \
+ } while (0)
+
+static inline int
+validate_debug_offsets_layout(struct _Py_DebugOffsets *debug_offsets)
+{
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(runtime_state);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ runtime_state,
+ interpreters_head,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ sizeof(_PyRuntimeState));
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_state);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ threads_head,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ INTERP_STATE_BUFFER_SIZE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ threads_main,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ INTERP_STATE_BUFFER_SIZE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ gil_runtime_state_locked,
+ sizeof(int),
+ _Alignof(int),
+ INTERP_STATE_BUFFER_SIZE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ gil_runtime_state_holder,
+ sizeof(PyThreadState *),
+ _Alignof(PyThreadState *),
+ INTERP_STATE_BUFFER_SIZE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ code_object_generation,
+ sizeof(uint64_t),
+ _Alignof(uint64_t),
+ INTERP_STATE_BUFFER_SIZE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_state,
+ tlbc_generation,
+ sizeof(uint32_t),
+ _Alignof(uint32_t),
+ INTERP_STATE_BUFFER_SIZE);
+
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(thread_state, SIZEOF_THREAD_STATE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ thread_state,
+ next,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_THREAD_STATE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ thread_state,
+ current_frame,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_THREAD_STATE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ thread_state,
+ native_thread_id,
+ sizeof(unsigned long),
+ _Alignof(unsigned long),
+ SIZEOF_THREAD_STATE);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ thread_state,
+ datastack_chunk,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_THREAD_STATE);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_frame);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ previous,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_INTERP_FRAME);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ executable,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_INTERP_FRAME);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ instr_ptr,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_INTERP_FRAME);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ owner,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_INTERP_FRAME);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ stackpointer,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_INTERP_FRAME);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ interpreter_frame,
+ tlbc_index,
+ sizeof(int32_t),
+ _Alignof(int32_t),
+ SIZEOF_INTERP_FRAME);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(code_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ qualname,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_CODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ filename,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_CODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ linetable,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_CODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ firstlineno,
+ sizeof(int),
+ _Alignof(int),
+ SIZEOF_CODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ co_code_adaptive,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_CODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ code_object,
+ co_tlbc,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_CODE_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(pyobject);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ pyobject,
+ ob_type,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_PYOBJECT);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(type_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ type_object,
+ tp_flags,
+ sizeof(unsigned long),
+ _Alignof(unsigned long),
+ SIZEOF_TYPE_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(set_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ set_object,
+ used,
+ sizeof(Py_ssize_t),
+ _Alignof(Py_ssize_t),
+ SIZEOF_SET_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ set_object,
+ mask,
+ sizeof(Py_ssize_t),
+ _Alignof(Py_ssize_t),
+ SIZEOF_SET_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ set_object,
+ table,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_SET_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(long_object, SIZEOF_LONG_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ long_object,
+ lv_tag,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_LONG_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ long_object,
+ ob_digit,
+ sizeof(digit),
+ _Alignof(digit),
+ SIZEOF_LONG_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(bytes_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ bytes_object,
+ ob_size,
+ sizeof(Py_ssize_t),
+ _Alignof(Py_ssize_t),
+ SIZEOF_BYTES_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ bytes_object,
+ ob_sval,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_BYTES_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(unicode_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ unicode_object,
+ length,
+ sizeof(Py_ssize_t),
+ _Alignof(Py_ssize_t),
+ SIZEOF_UNICODE_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ unicode_object,
+ asciiobject_size,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_UNICODE_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(gen_object);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ gen_object,
+ gi_frame_state,
+ sizeof(int8_t),
+ _Alignof(int8_t),
+ SIZEOF_GEN_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ gen_object,
+ gi_iframe,
+ FIELD_SIZE(PyGenObject, gi_iframe),
+ _Alignof(_PyInterpreterFrame),
+ SIZEOF_GEN_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(
+ llist_node,
+ next,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_LLIST_NODE);
+
+ return 0;
+}
+
+static inline int
+validate_async_debug_offsets_layout(struct _Py_AsyncioModuleDebugOffsets *debug_offsets)
+{
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(asyncio_task_object, SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_name,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_awaited_by,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_is_task,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_awaited_by_is_set,
+ sizeof(char),
+ _Alignof(char),
+ SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_coro,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ SIZEOF_TASK_OBJ);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_task_object,
+ task_node,
+ SIZEOF_LLIST_NODE,
+ _Alignof(struct llist_node),
+ SIZEOF_TASK_OBJ);
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_interpreter_state);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_interpreter_state,
+ asyncio_tasks_head,
+ SIZEOF_LLIST_NODE,
+ _Alignof(struct llist_node),
+ sizeof(PyInterpreterState));
+
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_thread_state);
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_thread_state,
+ asyncio_running_loop,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ sizeof(_PyThreadStateImpl));
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_thread_state,
+ asyncio_running_task,
+ sizeof(uintptr_t),
+ _Alignof(uintptr_t),
+ sizeof(_PyThreadStateImpl));
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
+ asyncio_thread_state,
+ asyncio_tasks_head,
+ SIZEOF_LLIST_NODE,
+ _Alignof(struct llist_node),
+ sizeof(_PyThreadStateImpl));
+
+ return 0;
+}
+
+#undef PY_REMOTE_DEBUG_VALIDATE_SECTION
+#undef PY_REMOTE_DEBUG_VALIDATE_READ_SECTION
+#undef PY_REMOTE_DEBUG_VALIDATE_FIELD
+#undef PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD
+#undef FIELD_SIZE
+
/* ============================================================================
* STRUCTSEQ TYPE DEFINITIONS
* ============================================================================ */
@@ -434,7 +917,7 @@ validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets)
return -1;
}
- return 0;
+ return validate_debug_offsets_layout(debug_offsets);
}
// Generic function to iterate through all threads
@@ -877,8 +1360,13 @@ read_async_debug(
int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, async_debug_addr, size, &unwinder->async_debug_offsets);
if (result < 0) {
set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read AsyncioDebug offsets");
+ return result;
}
- return result;
+ if (validate_async_debug_offsets_layout(&unwinder->async_debug_offsets) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid AsyncioDebug offsets");
+ return PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS;
+ }
+ return 0;
}
/* ============================================================================
@@ -2054,10 +2542,15 @@ static void *
find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr)
{
for (size_t i = 0; i < chunks->count; ++i) {
+ if (chunks->chunks[i].size <= offsetof(_PyStackChunk, data)) {
+ continue;
+ }
uintptr_t base = chunks->chunks[i].remote_addr + offsetof(_PyStackChunk, data);
size_t payload = chunks->chunks[i].size - offsetof(_PyStackChunk, data);
- if (remote_ptr >= base && remote_ptr < base + payload) {
+ if (payload >= SIZEOF_INTERP_FRAME &&
+ remote_ptr >= base &&
+ remote_ptr <= base + payload - SIZEOF_INTERP_FRAME) {
return (char *)chunks->chunks[i].local_copy + (remote_ptr - chunks->chunks[i].remote_addr);
}
}
@@ -2624,7 +3117,11 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
// Try to read async debug offsets, but don't fail if they're not available
self->async_debug_offsets_available = 1;
- if (read_async_debug(self) < 0) {
+ int async_debug_result = read_async_debug(self);
+ if (async_debug_result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) {
+ return -1;
+ }
+ if (async_debug_result < 0) {
PyErr_Clear();
memset(&self->async_debug_offsets, 0, sizeof(self->async_debug_offsets));
self->async_debug_offsets_available = 0;

View File

@ -1,64 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 13 Apr 2026 03:40:54 +0200
Subject: 00482: CVE-2026-6100
Fix a possible UAF in {LZMA,BZ2,_Zlib}Decompressor
Co-authored-by: Stan Ulbrych <stan@python.org>
---
.../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 9e85e0de42..055ce82e7d 100644
--- a/Modules/_bz2module.c
+++ b/Modules/_bz2module.c
@@ -593,6 +593,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 462c2181fa..6785dc5673 100644
--- a/Modules/_lzmamodule.c
+++ b/Modules/_lzmamodule.c
@@ -1120,6 +1120,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 5b6b0c5cac..a86aa5fdbb 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -1675,6 +1675,7 @@ decompress(ZlibDecompressor *self, uint8_t *data,
return result;
error:
+ self->zst.next_in = NULL;
Py_XDECREF(result);
return NULL;
}

View File

@ -0,0 +1,124 @@
From 4f17f6e04534d93fbd23862f9f290d3a281ab30b Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou@gmail.com>
Date: Fri, 5 Jun 2026 10:50:14 +0200
Subject: [PATCH] [3.14] gh-149144: Use decodeURIComponent() for UTF-8 support
in js_output() (GH-149157)
(cherry picked from commit 461b1d96313de02992d284c1782be9aff24586c9)
Co-authored-by: Seth Larson <seth@python.org>
---
Lib/http/cookies.py | 6 +++---
Lib/test/test_http_cookies.py | 27 ++++++++++++++-------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py
index 5c5b14788dc2f09..abebb4b69fd05f4 100644
--- a/Lib/http/cookies.py
+++ b/Lib/http/cookies.py
@@ -391,18 +391,18 @@ def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.OutputString())
def js_output(self, attrs=None):
- import base64
+ import urllib.parse
# Print javascript
output_string = self.OutputString(attrs)
if _has_control_character(output_string):
raise CookieError("Control characters are not allowed in cookies")
# Base64-encode value to avoid template
# injection in cookie values.
- output_encoded = base64.b64encode(output_string.encode('utf-8')).decode("ascii")
+ output_encoded = urllib.parse.quote(output_string, safe='', encoding='utf-8')
return """
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob(\"%s\");
+ document.cookie = decodeURIComponent(\"%s\");
// end hiding -->
</script>
""" % (output_encoded,)
diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py
index 4884b07c95b9c50..3ace949afd403eb 100644
--- a/Lib/test/test_http_cookies.py
+++ b/Lib/test/test_http_cookies.py
@@ -1,11 +1,11 @@
# Simple test suite for http/cookies.py
-import base64
import copy
import unittest
import doctest
from http import cookies
import pickle
from test import support
+import urllib.parse
class CookieTests(unittest.TestCase):
@@ -152,19 +152,19 @@ def test_load(self):
self.assertEqual(C.output(['path']),
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
- cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii')
+ cookie_encoded = urllib.parse.quote('Customer="WILE_E_COYOTE"; Path=/acme; Version=1', safe='', encoding='utf-8')
self.assertEqual(C.js_output(), fr"""
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob("{cookie_encoded}");
+ document.cookie = decodeURIComponent("{cookie_encoded}");
// end hiding -->
</script>
""")
- cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii')
+ cookie_encoded = urllib.parse.quote('Customer="WILE_E_COYOTE"; Path=/acme', safe='', encoding='utf-8')
self.assertEqual(C.js_output(['path']), fr"""
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob("{cookie_encoded}");
+ document.cookie = decodeURIComponent("{cookie_encoded}");
// end hiding -->
</script>
""")
@@ -269,19 +269,19 @@ def test_quoted_meta(self):
self.assertEqual(C.output(['path']),
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
- expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii')
+ expected_encoded_cookie = urllib.parse.quote('Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1', safe='', encoding='utf-8')
self.assertEqual(C.js_output(), fr"""
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob("{expected_encoded_cookie}");
+ document.cookie = decodeURIComponent("{expected_encoded_cookie}");
// end hiding -->
</script>
""")
- expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii')
+ expected_encoded_cookie = urllib.parse.quote('Customer=\"WILE_E_COYOTE\"; Path=/acme', safe='', encoding='utf-8')
self.assertEqual(C.js_output(['path']), fr"""
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob("{expected_encoded_cookie}");
+ document.cookie = decodeURIComponent("{expected_encoded_cookie}");
// end hiding -->
</script>
""")
@@ -372,13 +372,14 @@ def test_setter(self):
self.assertEqual(
M.output(),
"Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i))
- expected_encoded_cookie = base64.b64encode(
- ("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii")
- ).decode('ascii')
+ expected_encoded_cookie = urllib.parse.quote(
+ "%s=%s; Path=/foo" % (i, "%s_coded_val" % i),
+ safe='', encoding='utf-8',
+ )
expected_js_output = """
<script type="text/javascript">
<!-- begin hiding
- document.cookie = atob("%s");
+ document.cookie = decodeURIComponent("%s");
// end hiding -->
</script>
""" % (expected_encoded_cookie,)

View File

@ -45,11 +45,11 @@ URL: https://www.python.org/
# WARNING When rebasing to a new Python version, # WARNING When rebasing to a new Python version,
# remember to update the python3-docs package as well # remember to update the python3-docs package as well
%global general_version %{pybasever}.4 %global general_version %{pybasever}.5
#global prerel ... #global prerel ...
%global upstream_version %{general_version}%{?prerel} %global upstream_version %{general_version}%{?prerel}
Version: %{general_version}%{?prerel:~%{prerel}} Version: %{general_version}%{?prerel:~%{prerel}}
Release: 2%{?dist} Release: 1%{?dist}
License: Python-2.0.1 License: Python-2.0.1
@ -109,31 +109,30 @@ License: Python-2.0.1
# This needs to be manually updated when we update Python. # This needs to be manually updated when we update Python.
# Explore the sources tarball (you need the version before %%prep is executed): # Explore the sources tarball (you need the version before %%prep is executed):
# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl # $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl
%global pip_version 26.0.1 %global pip_version 26.1.1
%global setuptools_version 79.0.1 %global setuptools_version 79.0.1
# All of those also include a list of indirect bundled libs: # All of those also include a list of indirect bundled libs:
# pip # pip
# $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) # $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt)
%global pip_bundled_provides %{expand: %global pip_bundled_provides %{expand:
Provides: bundled(python3dist(cachecontrol)) = 0.14.4 Provides: bundled(python3dist(cachecontrol)) = 0.14.4
Provides: bundled(python3dist(certifi)) = 2026.1.4 Provides: bundled(python3dist(certifi)) = 2026.2.25
Provides: bundled(python3dist(dependency-groups)) = 1.3.1
Provides: bundled(python3dist(distlib)) = 0.4 Provides: bundled(python3dist(distlib)) = 0.4
Provides: bundled(python3dist(distro)) = 1.9 Provides: bundled(python3dist(distro)) = 1.9
Provides: bundled(python3dist(idna)) = 3.11 Provides: bundled(python3dist(idna)) = 3.11
Provides: bundled(python3dist(msgpack)) = 1.1.2 Provides: bundled(python3dist(msgpack)) = 1.1.2
Provides: bundled(python3dist(packaging)) = 26 Provides: bundled(python3dist(packaging)) = 26.2
Provides: bundled(python3dist(platformdirs)) = 4.5.1 Provides: bundled(python3dist(platformdirs)) = 4.5.1
Provides: bundled(python3dist(pygments)) = 2.19.2 Provides: bundled(python3dist(pygments)) = 2.19.2
Provides: bundled(python3dist(pyproject-hooks)) = 1.2 Provides: bundled(python3dist(pyproject-hooks)) = 1.2
Provides: bundled(python3dist(requests)) = 2.32.5 Provides: bundled(python3dist(requests)) = 2.33.1
Provides: bundled(python3dist(resolvelib)) = 1.2.1 Provides: bundled(python3dist(resolvelib)) = 1.2.1
Provides: bundled(python3dist(rich)) = 14.2 Provides: bundled(python3dist(rich)) = 14.2
Provides: bundled(python3dist(setuptools)) = 70.3 Provides: bundled(python3dist(setuptools)) = 70.3
Provides: bundled(python3dist(tomli)) = 2.3 Provides: bundled(python3dist(tomli)) = 2.3.1
Provides: bundled(python3dist(tomli-w)) = 1.2 Provides: bundled(python3dist(tomli-w)) = 1.2
Provides: bundled(python3dist(truststore)) = 0.10.4 Provides: bundled(python3dist(truststore)) = 0.10.4
Provides: bundled(python3dist(urllib3)) = 1.26.20 Provides: bundled(python3dist(urllib3)) = 2.6.3
} }
# setuptools # setuptools
# vendor.txt not in .whl # vendor.txt not in .whl
@ -438,29 +437,11 @@ Patch475: 00475-cve-2025-15367.patch
# direct call to the check function. # direct call to the check function.
Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch
# 00479 # 97404b2cf62e545c2d41be7ccfed4e74da9ee665 # 00487 #
# CVE-2026-1502 # Fixup for CVE-2026-6019
# # Use decodeURIComponent() for UTF-8 support in js_output()
# Reject CR/LF in HTTP tunnel request headers # Resolved upstream: https://github.com/python/cpython/issues/149144
Patch479: 00479-cve-2026-1502.patch Patch487: 00487-fixup-for-CVE-2026-6019.patch
# 00480 # 858691f36890b33e713f330d24c6670329695c2e
# CVE-2026-4786
#
# Fix webbrowser `%%action` substitution bypass of dash-prefix check
Patch480: 00480-cve-2026-4786.patch
# 00481 # 4c1fd39918651c4559a4835d42b86639a192c2c5
# CVE-2026-5713
#
# Validate remote debug offset tables on load
Patch481: 00481-cve-2026-5713.patch
# 00482 # 69f14bc306fc62400d45565faa980b77858b9151
# CVE-2026-6100
#
# Fix a possible UAF in {LZMA,BZ2,_Zlib}Decompressor
Patch482: 00482-cve-2026-6100.patch
# (New patches go here ^^^) # (New patches go here ^^^)
# #
@ -1999,6 +1980,16 @@ CheckPython freethreading
# ====================================================== # ======================================================
%changelog %changelog
* Tue Jun 09 2026 Miro Hrončok <mhroncok@redhat.com> - 3.14.5-1
- Update to 3.14.5
Resolves: RHEL-176147
* Tue Jun 09 2026 Miro Hrončok <mhroncok@redhat.com> - 3.14.5~rc1-1
- Update to 3.14.5rc1
- Move back to the generational from the incremental garbage collector
- Security fix for CVE-2026-6019
Resolves: RHEL-176147
* Thu Apr 16 2026 Charalampos Stratakis <cstratak@redhat.com> - 3.14.4-2 * Thu Apr 16 2026 Charalampos Stratakis <cstratak@redhat.com> - 3.14.4-2
- Security fixes for CVE-2026-1502, CVE-2026-4786, CVE-2026-5713, CVE-2026-6100 - Security fixes for CVE-2026-1502, CVE-2026-4786, CVE-2026-5713, CVE-2026-6100
Resolves: RHEL-168121, RHEL-167887 Resolves: RHEL-168121, RHEL-167887

View File

@ -1 +1 @@
SHA512 (Python-3.14.4.tar.xz) = 89a7f8b8a31f48d150badb4751df137d47d9014c9c422649a1a55aef5618aa7f0259dd18c151e6804fa8312c6a21544332a9f630ee81150dc00505637e62bb8c SHA512 (Python-3.14.5.tar.xz) = efbaf629703cd004f6b7bc75fb16df794185589adaf8807cd45928f212271045a399df3cd9573e47c8708fb5c5002f9d4efe4e41dde4313b81a3e9d73158769f