Compare commits
10 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
|
5a93ef3ac0
|
|||
|
3a530bad02
|
|||
|
706c7b4cac
|
|||
|
f41d0d940b
|
|||
|
c99dacd908
|
|||
|
3206c36a35
|
|||
|
16a4b703f5
|
|||
|
597c86f858
|
|||
|
8e0da3e0be
|
|||
|
|
5a4398f438
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,4 +2,5 @@
|
|||||||
*.obscpio
|
*.obscpio
|
||||||
_build.*
|
_build.*
|
||||||
.pbuild
|
.pbuild
|
||||||
|
*.orig
|
||||||
python314-*-build/
|
python314-*-build/
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
From 5a8bfd878f086e28f0849bbc3970ad92f6ba37dc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Seth Michael Larson <seth@python.org>
|
|
||||||
Date: Fri, 23 Jan 2026 08:59:35 -0600
|
|
||||||
Subject: [PATCH] gh-144125: email: verify headers are sound in BytesGenerator
|
|
||||||
(cherry picked from commit 052e55e7d44718fe46cbba0ca995cb8fcc359413)
|
|
||||||
|
|
||||||
Co-authored-by: Seth Michael Larson <seth@python.org>
|
|
||||||
Co-authored-by: Denis Ledoux <dle@odoo.com>
|
|
||||||
Co-authored-by: Denis Ledoux <5822488+beledouxdenis@users.noreply.github.com>
|
|
||||||
Co-authored-by: Petr Viktorin <302922+encukou@users.noreply.github.com>
|
|
||||||
Co-authored-by: Bas Bloemsaat <1586868+basbloemsaat@users.noreply.github.com>
|
|
||||||
---
|
|
||||||
Lib/email/generator.py | 12 +++++++++-
|
|
||||||
Lib/test/test_email/test_generator.py | 4 ++-
|
|
||||||
Lib/test/test_email/test_policy.py | 6 ++++-
|
|
||||||
Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst | 4 +++
|
|
||||||
4 files changed, 23 insertions(+), 3 deletions(-)
|
|
||||||
create mode 100644 Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
|
|
||||||
|
|
||||||
Index: Python-3.14.2/Lib/email/generator.py
|
|
||||||
===================================================================
|
|
||||||
--- Python-3.14.2.orig/Lib/email/generator.py 2026-01-28 22:15:51.075267925 +0100
|
|
||||||
+++ Python-3.14.2/Lib/email/generator.py 2026-01-28 22:15:56.251194626 +0100
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
NLCRE = re.compile(r'\r\n|\r|\n')
|
|
||||||
fcre = re.compile(r'^From ', re.MULTILINE)
|
|
||||||
NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
|
|
||||||
+NEWLINE_WITHOUT_FWSP_BYTES = re.compile(br'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
|
|
||||||
|
|
||||||
|
|
||||||
class Generator:
|
|
||||||
@@ -429,7 +430,16 @@
|
|
||||||
# This is almost the same as the string version, except for handling
|
|
||||||
# strings with 8bit bytes.
|
|
||||||
for h, v in msg.raw_items():
|
|
||||||
- self._fp.write(self.policy.fold_binary(h, v))
|
|
||||||
+ folded = self.policy.fold_binary(h, v)
|
|
||||||
+ if self.policy.verify_generated_headers:
|
|
||||||
+ linesep = self.policy.linesep.encode()
|
|
||||||
+ if not folded.endswith(linesep):
|
|
||||||
+ raise HeaderWriteError(
|
|
||||||
+ f'folded header does not end with {linesep!r}: {folded!r}')
|
|
||||||
+ if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)):
|
|
||||||
+ raise HeaderWriteError(
|
|
||||||
+ f'folded header contains newline: {folded!r}')
|
|
||||||
+ self._fp.write(folded)
|
|
||||||
# A blank line always separates headers from body
|
|
||||||
self.write(self._NL)
|
|
||||||
|
|
||||||
Index: Python-3.14.2/Lib/test/test_email/test_generator.py
|
|
||||||
===================================================================
|
|
||||||
--- Python-3.14.2.orig/Lib/test/test_email/test_generator.py 2026-01-28 22:15:52.693627763 +0100
|
|
||||||
+++ Python-3.14.2/Lib/test/test_email/test_generator.py 2026-01-28 22:15:56.251344799 +0100
|
|
||||||
@@ -313,7 +313,7 @@
|
|
||||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
|
||||||
|
|
||||||
def test_verify_generated_headers(self):
|
|
||||||
- """gh-121650: by default the generator prevents header injection"""
|
|
||||||
+ # gh-121650: by default the generator prevents header injection
|
|
||||||
class LiteralHeader(str):
|
|
||||||
name = 'Header'
|
|
||||||
def fold(self, **kwargs):
|
|
||||||
@@ -334,6 +334,8 @@
|
|
||||||
|
|
||||||
with self.assertRaises(email.errors.HeaderWriteError):
|
|
||||||
message.as_string()
|
|
||||||
+ with self.assertRaises(email.errors.HeaderWriteError):
|
|
||||||
+ message.as_bytes()
|
|
||||||
|
|
||||||
|
|
||||||
class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
|
|
||||||
Index: Python-3.14.2/Lib/test/test_email/test_policy.py
|
|
||||||
===================================================================
|
|
||||||
--- Python-3.14.2.orig/Lib/test/test_email/test_policy.py 2026-01-28 22:15:52.703671956 +0100
|
|
||||||
+++ Python-3.14.2/Lib/test/test_email/test_policy.py 2026-01-28 22:15:56.251499922 +0100
|
|
||||||
@@ -296,7 +296,7 @@
|
|
||||||
policy.fold("Subject", subject)
|
|
||||||
|
|
||||||
def test_verify_generated_headers(self):
|
|
||||||
- """Turning protection off allows header injection"""
|
|
||||||
+ # Turning protection off allows header injection
|
|
||||||
policy = email.policy.default.clone(verify_generated_headers=False)
|
|
||||||
for text in (
|
|
||||||
'Header: Value\r\nBad: Injection\r\n',
|
|
||||||
@@ -319,6 +319,10 @@
|
|
||||||
message.as_string(),
|
|
||||||
f"{text}\nBody",
|
|
||||||
)
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ message.as_bytes(),
|
|
||||||
+ f"{text}\nBody".encode(),
|
|
||||||
+ )
|
|
||||||
|
|
||||||
# XXX: Need subclassing tests.
|
|
||||||
# For adding subclassed objects, make sure the usual rules apply (subclass
|
|
||||||
Index: Python-3.14.2/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
||||||
+++ Python-3.14.2/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst 2026-01-28 22:15:56.251667056 +0100
|
|
||||||
@@ -0,0 +1,4 @@
|
|
||||||
+:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) headers
|
|
||||||
+that are unsafely folded or delimited; see
|
|
||||||
+:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas
|
|
||||||
+Bloemsaat and Petr Viktorin in :gh:`121650`).
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
From df45bd1aafc3b6792d43661207d2b7eb3a14d214 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Seth Michael Larson <seth@python.org>
|
|
||||||
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 <seth@python.org>
|
|
||||||
Co-authored-by: Denis Ledoux <dle@odoo.com>
|
|
||||||
---
|
|
||||||
Lib/email/_header_value_parser.py | 15 +++++++++++-
|
|
||||||
.../test_email/test__header_value_parser.py | 23 +++++++++++++++++++
|
|
||||||
...-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
|
|
||||||
|
|
||||||
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
|
|
||||||
index 68c2cf9585c5b4..51727688c059ed 100644
|
|
||||||
--- a/Lib/email/_header_value_parser.py
|
|
||||||
+++ b/Lib/email/_header_value_parser.py
|
|
||||||
@@ -101,6 +101,12 @@ def make_quoted_pairs(value):
|
|
||||||
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}"'
|
|
||||||
@@ -939,7 +945,7 @@ def value(self):
|
|
||||||
return ' '
|
|
||||||
|
|
||||||
def startswith_fws(self):
|
|
||||||
- return True
|
|
||||||
+ return self and self[0] in WSP
|
|
||||||
|
|
||||||
|
|
||||||
class ValueTerminal(Terminal):
|
|
||||||
@@ -2959,6 +2965,13 @@ def _refold_parse_tree(parse_tree, *, policy):
|
|
||||||
[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)
|
|
||||||
diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py
|
|
||||||
index 426ec4644e3096..e28fe3892015b9 100644
|
|
||||||
--- a/Lib/test/test_email/test__header_value_parser.py
|
|
||||||
+++ b/Lib/test/test_email/test__header_value_parser.py
|
|
||||||
@@ -3294,6 +3294,29 @@ def test_address_list_with_specials_in_long_quoted_string(self):
|
|
||||||
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)<spy@example.org>',
|
|
||||||
+ '(loremipsumdolorsitametconsecteturadipi)<spy@example.org>\n'),
|
|
||||||
+ ('<spy@example.org>(loremipsumdolorsitametconsecteturadipi)',
|
|
||||||
+ '<spy@example.org>(loremipsumdolorsitametconsecteturadipi)\n'),
|
|
||||||
+ ('(loremipsum dolorsitametconsecteturadipi)<spy@example.org>',
|
|
||||||
+ '(loremipsum dolorsitametconsecteturadipi)<spy@example.org>\n'),
|
|
||||||
+ ('<spy@example.org>(loremipsum dolorsitametconsecteturadipi)',
|
|
||||||
+ '<spy@example.org>(loremipsum\n dolorsitametconsecteturadipi)\n'),
|
|
||||||
+ ('(Escaped \\( \\) chars \\\\ in comments stay escaped)<spy@example.org>',
|
|
||||||
+ '(Escaped \\( \\) chars \\\\ in comments stay\n escaped)<spy@example.org>\n'),
|
|
||||||
+ ('((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>',
|
|
||||||
+ '((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>\n'),
|
|
||||||
+ ('((loremipsum)(loremipsum)(loremipsum) (loremipsum))<spy@example.org>',
|
|
||||||
+ '((loremipsum)(loremipsum)(loremipsum)\n (loremipsum))<spy@example.org>\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.
|
|
||||||
diff --git a/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst b/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000000000..c3d864936884ac
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
|
|
||||||
@@ -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.
|
|
||||||
196
CVE-2025-12781-b64decode-alt-chars.patch
Normal file
196
CVE-2025-12781-b64decode-alt-chars.patch
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
From f922c02c529d25d61aa9c28a8192639c1fce8d4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
Date: Wed, 5 Nov 2025 20:12:31 +0200
|
||||||
|
Subject: [PATCH] gh-125346: Add more base64 tests
|
||||||
|
|
||||||
|
Add more tests for the altchars argument of b64decode() and for the map01
|
||||||
|
argument of b32decode().
|
||||||
|
---
|
||||||
|
Doc/library/base64.rst | 18 ++--
|
||||||
|
Lib/base64.py | 40 +++++++-
|
||||||
|
Lib/test/test_base64.py | 45 ++++++++--
|
||||||
|
Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst | 5 +
|
||||||
|
4 files changed, 91 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
Index: Python-3.14.3/Doc/library/base64.rst
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Doc/library/base64.rst 2026-02-03 16:32:20.000000000 +0100
|
||||||
|
+++ Python-3.14.3/Doc/library/base64.rst 2026-02-05 18:27:59.082523095 +0100
|
||||||
|
@@ -77,15 +77,20 @@
|
||||||
|
A :exc:`binascii.Error` exception is raised
|
||||||
|
if *s* is incorrectly padded.
|
||||||
|
|
||||||
|
- If *validate* is ``False`` (the default), characters that are neither
|
||||||
|
+ If *validate* is false (the default), characters that are neither
|
||||||
|
in the normal base-64 alphabet nor the alternative alphabet are
|
||||||
|
- discarded prior to the padding check. If *validate* is ``True``,
|
||||||
|
- these non-alphabet characters in the input result in a
|
||||||
|
- :exc:`binascii.Error`.
|
||||||
|
+ discarded prior to the padding check, but the ``+`` and ``/`` characters
|
||||||
|
+ keep their meaning if they are not in *altchars* (they will be discarded
|
||||||
|
+ in future Python versions).
|
||||||
|
+ If *validate* is true, these non-alphabet characters in the input
|
||||||
|
+ result in a :exc:`binascii.Error`.
|
||||||
|
|
||||||
|
For more information about the strict base64 check, see :func:`binascii.a2b_base64`
|
||||||
|
|
||||||
|
- May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2.
|
||||||
|
+ .. deprecated:: next
|
||||||
|
+ Accepting the ``+`` and ``/`` characters with an alternative alphabet
|
||||||
|
+ is now deprecated.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: standard_b64encode(s)
|
||||||
|
|
||||||
|
@@ -116,6 +121,9 @@
|
||||||
|
``/`` in the standard Base64 alphabet, and return the decoded
|
||||||
|
:class:`bytes`.
|
||||||
|
|
||||||
|
+ .. deprecated:: next
|
||||||
|
+ Accepting the ``+`` and ``/`` characters is now deprecated.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: b32encode(s)
|
||||||
|
|
||||||
|
Index: Python-3.14.3/Lib/base64.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/base64.py 2026-02-05 18:27:49.507586298 +0100
|
||||||
|
+++ Python-3.14.3/Lib/base64.py 2026-02-05 18:27:59.082973222 +0100
|
||||||
|
@@ -69,20 +69,39 @@
|
||||||
|
The result is returned as a bytes object. A binascii.Error is raised if
|
||||||
|
s is incorrectly padded.
|
||||||
|
|
||||||
|
- If validate is False (the default), characters that are neither in the
|
||||||
|
+ If validate is false (the default), characters that are neither in the
|
||||||
|
normal base-64 alphabet nor the alternative alphabet are discarded prior
|
||||||
|
- to the padding check. If validate is True, these non-alphabet characters
|
||||||
|
+ to the padding check. If validate is true, these non-alphabet characters
|
||||||
|
in the input result in a binascii.Error.
|
||||||
|
For more information about the strict base64 check, see:
|
||||||
|
|
||||||
|
https://docs.python.org/3.11/library/binascii.html#binascii.a2b_base64
|
||||||
|
"""
|
||||||
|
s = _bytes_from_decode_data(s)
|
||||||
|
+ badchar = None
|
||||||
|
if altchars is not None:
|
||||||
|
altchars = _bytes_from_decode_data(altchars)
|
||||||
|
- assert len(altchars) == 2, repr(altchars)
|
||||||
|
+ if len(altchars) != 2:
|
||||||
|
+ raise ValueError(f'invalid altchars: {altchars!r}')
|
||||||
|
+ for b in b'+/':
|
||||||
|
+ if b not in altchars and b in s:
|
||||||
|
+ badchar = b
|
||||||
|
+ break
|
||||||
|
s = s.translate(bytes.maketrans(altchars, b'+/'))
|
||||||
|
- return binascii.a2b_base64(s, strict_mode=validate)
|
||||||
|
+ result = binascii.a2b_base64(s, strict_mode=validate)
|
||||||
|
+ if badchar is not None:
|
||||||
|
+ import warnings
|
||||||
|
+ if validate:
|
||||||
|
+ warnings.warn(f'invalid character {chr(badchar)!a} in Base64 data '
|
||||||
|
+ f'with altchars={altchars!r} and validate=True '
|
||||||
|
+ f'will be an error in future Python versions',
|
||||||
|
+ DeprecationWarning, stacklevel=2)
|
||||||
|
+ else:
|
||||||
|
+ warnings.warn(f'invalid character {chr(badchar)!a} in Base64 data '
|
||||||
|
+ f'with altchars={altchars!r} and validate=False '
|
||||||
|
+ f'will be discarded in future Python versions',
|
||||||
|
+ FutureWarning, stacklevel=2)
|
||||||
|
+ return result
|
||||||
|
|
||||||
|
|
||||||
|
def standard_b64encode(s):
|
||||||
|
@@ -127,8 +146,19 @@
|
||||||
|
The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
|
"""
|
||||||
|
s = _bytes_from_decode_data(s)
|
||||||
|
+ badchar = None
|
||||||
|
+ for b in b'+/':
|
||||||
|
+ if b in s:
|
||||||
|
+ badchar = b
|
||||||
|
+ break
|
||||||
|
s = s.translate(_urlsafe_decode_translation)
|
||||||
|
- return b64decode(s)
|
||||||
|
+ result = binascii.a2b_base64(s, strict_mode=False)
|
||||||
|
+ if badchar is not None:
|
||||||
|
+ import warnings
|
||||||
|
+ warnings.warn(f'invalid character {chr(badchar)!a} in URL-safe Base64 data '
|
||||||
|
+ f'will be discarded in future Python versions',
|
||||||
|
+ FutureWarning, stacklevel=2)
|
||||||
|
+ return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Index: Python-3.14.3/Lib/test/test_base64.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/test/test_base64.py 2026-02-05 18:27:50.870195970 +0100
|
||||||
|
+++ Python-3.14.3/Lib/test/test_base64.py 2026-02-05 18:27:59.083266184 +0100
|
||||||
|
@@ -242,6 +242,25 @@
|
||||||
|
eq(base64.b64decode(data, altchars=altchars_str), res)
|
||||||
|
eq(base64.b64decode(data_str, altchars=altchars_str), res)
|
||||||
|
|
||||||
|
+ def test_b64decode_altchars(self):
|
||||||
|
+ # Test with arbitrary alternative characters
|
||||||
|
+ eq = self.assertEqual
|
||||||
|
+ res = b'\xd3V\xbeo\xf7\x1d'
|
||||||
|
+ for altchars in b'*$', b'+/', b'/+', b'+_', b'-+', b'-/', b'/_':
|
||||||
|
+ data = b'01a%cb%ccd' % tuple(altchars)
|
||||||
|
+ data_str = data.decode('ascii')
|
||||||
|
+ altchars_str = altchars.decode('ascii')
|
||||||
|
+
|
||||||
|
+ eq(base64.b64decode(data, altchars=altchars), res)
|
||||||
|
+ eq(base64.b64decode(data_str, altchars=altchars), res)
|
||||||
|
+ eq(base64.b64decode(data, altchars=altchars_str), res)
|
||||||
|
+ eq(base64.b64decode(data_str, altchars=altchars_str), res)
|
||||||
|
+
|
||||||
|
+ self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+')
|
||||||
|
+ self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+/-')
|
||||||
|
+ self.assertRaises(ValueError, base64.b64decode, '', altchars='+')
|
||||||
|
+ self.assertRaises(ValueError, base64.b64decode, '', altchars='+/-')
|
||||||
|
+
|
||||||
|
def test_b64decode_padding_error(self):
|
||||||
|
self.assertRaises(binascii.Error, base64.b64decode, b'abc')
|
||||||
|
self.assertRaises(binascii.Error, base64.b64decode, 'abc')
|
||||||
|
@@ -273,13 +292,25 @@
|
||||||
|
with self.assertRaises(binascii.Error):
|
||||||
|
base64.b64decode(bstr.decode('ascii'), validate=True)
|
||||||
|
|
||||||
|
- # Normal alphabet characters not discarded when alternative given
|
||||||
|
- res = b'\xfb\xef\xff'
|
||||||
|
- self.assertEqual(base64.b64decode(b'++//', validate=True), res)
|
||||||
|
- self.assertEqual(base64.b64decode(b'++//', '-_', validate=True), res)
|
||||||
|
- self.assertEqual(base64.b64decode(b'--__', '-_', validate=True), res)
|
||||||
|
- self.assertEqual(base64.urlsafe_b64decode(b'++//'), res)
|
||||||
|
- self.assertEqual(base64.urlsafe_b64decode(b'--__'), res)
|
||||||
|
+ # Normal alphabet characters will be discarded when alternative given
|
||||||
|
+ with self.assertWarns(FutureWarning):
|
||||||
|
+ self.assertEqual(base64.b64decode(b'++++', altchars=b'-_'),
|
||||||
|
+ b'\xfb\xef\xbe')
|
||||||
|
+ with self.assertWarns(FutureWarning):
|
||||||
|
+ self.assertEqual(base64.b64decode(b'////', altchars=b'-_'),
|
||||||
|
+ b'\xff\xff\xff')
|
||||||
|
+ with self.assertWarns(DeprecationWarning):
|
||||||
|
+ self.assertEqual(base64.b64decode(b'++++', altchars=b'-_', validate=True),
|
||||||
|
+ b'\xfb\xef\xbe')
|
||||||
|
+ with self.assertWarns(DeprecationWarning):
|
||||||
|
+ self.assertEqual(base64.b64decode(b'////', altchars=b'-_', validate=True),
|
||||||
|
+ b'\xff\xff\xff')
|
||||||
|
+ with self.assertWarns(FutureWarning):
|
||||||
|
+ self.assertEqual(base64.urlsafe_b64decode(b'++++'), b'\xfb\xef\xbe')
|
||||||
|
+ with self.assertWarns(FutureWarning):
|
||||||
|
+ self.assertEqual(base64.urlsafe_b64decode(b'////'), b'\xff\xff\xff')
|
||||||
|
+ with self.assertRaises(binascii.Error):
|
||||||
|
+ base64.b64decode(b'+/!', altchars=b'-_')
|
||||||
|
|
||||||
|
def test_b32encode(self):
|
||||||
|
eq = self.assertEqual
|
||||||
|
Index: Python-3.14.3/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.14.3/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst 2026-02-05 18:27:59.083646029 +0100
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+Accepting ``+`` and ``/`` characters with an alternative alphabet in
|
||||||
|
+:func:`base64.b64decode` and :func:`base64.urlsafe_b64decode` is now
|
||||||
|
+deprecated.
|
||||||
|
+In future Python versions they will be errors in the strict mode and
|
||||||
|
+discarded in the non-strict mode.
|
||||||
56
CVE-2025-15366-imap-ctrl-chars.patch
Normal file
56
CVE-2025-15366-imap-ctrl-chars.patch
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
From 7485ee5e2cf81d3e5ad0d9c3be73cecd2ab4eec7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Seth Michael Larson <seth@python.org>
|
||||||
|
Date: Fri, 16 Jan 2026 10:54:09 -0600
|
||||||
|
Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/imaplib.py | 4 +++-
|
||||||
|
Lib/test/test_imaplib.py | 6 ++++++
|
||||||
|
Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst | 1 +
|
||||||
|
3 files changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Index: Python-3.14.3/Lib/imaplib.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/imaplib.py 2026-02-05 18:55:16.834011332 +0100
|
||||||
|
+++ Python-3.14.3/Lib/imaplib.py 2026-02-05 18:55:22.293721093 +0100
|
||||||
|
@@ -131,7 +131,7 @@
|
||||||
|
# We compile these in _mode_xxx.
|
||||||
|
_Literal = br'.*{(?P<size>\d+)}$'
|
||||||
|
_Untagged_status = br'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?'
|
||||||
|
-
|
||||||
|
+_control_chars = re.compile(b'[\x00-\x1F\x7F]')
|
||||||
|
|
||||||
|
|
||||||
|
class IMAP4:
|
||||||
|
@@ -1108,6 +1108,8 @@
|
||||||
|
if arg is None: continue
|
||||||
|
if isinstance(arg, str):
|
||||||
|
arg = bytes(arg, self._encoding)
|
||||||
|
+ if _control_chars.search(arg):
|
||||||
|
+ raise ValueError("Control characters not allowed in commands")
|
||||||
|
data = data + b' ' + arg
|
||||||
|
|
||||||
|
literal = self.literal
|
||||||
|
Index: Python-3.14.3/Lib/test/test_imaplib.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/test/test_imaplib.py 2026-02-05 18:55:18.192739303 +0100
|
||||||
|
+++ Python-3.14.3/Lib/test/test_imaplib.py 2026-02-05 18:55:22.294159668 +0100
|
||||||
|
@@ -663,6 +663,12 @@
|
||||||
|
self.assertEqual(data[0], b'Returned to authenticated state. (Success)')
|
||||||
|
self.assertEqual(client.state, 'AUTH')
|
||||||
|
|
||||||
|
+ def test_control_characters(self):
|
||||||
|
+ client, _ = self._setup(SimpleIMAPHandler)
|
||||||
|
+ for c0 in support.control_characters_c0():
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ client.login(f'user{c0}', 'pass')
|
||||||
|
+
|
||||||
|
# property tests
|
||||||
|
|
||||||
|
def test_file_property_should_not_be_accessed(self):
|
||||||
|
Index: Python-3.14.3/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.14.3/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst 2026-02-05 18:55:22.294528513 +0100
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Reject control characters in IMAP commands.
|
||||||
56
CVE-2025-15367-poplib-ctrl-chars.patch
Normal file
56
CVE-2025-15367-poplib-ctrl-chars.patch
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
From b6f733b285b1c4f27dacb5c2e1f292c914e8b933 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Seth Michael Larson <seth@python.org>
|
||||||
|
Date: Fri, 16 Jan 2026 10:54:09 -0600
|
||||||
|
Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/poplib.py | 2 ++
|
||||||
|
Lib/test/test_poplib.py | 8 ++++++++
|
||||||
|
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.14.3/Lib/poplib.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/poplib.py 2026-02-05 19:22:19.999750697 +0100
|
||||||
|
+++ Python-3.14.3/Lib/poplib.py 2026-02-05 19:22:24.426236345 +0100
|
||||||
|
@@ -122,6 +122,8 @@
|
||||||
|
def _putcmd(self, line):
|
||||||
|
if self._debugging: print('*cmd*', repr(line))
|
||||||
|
line = bytes(line, self.encoding)
|
||||||
|
+ if re.search(b'[\x00-\x1F\x7F]', line):
|
||||||
|
+ raise ValueError('Control characters not allowed in commands')
|
||||||
|
self._putline(line)
|
||||||
|
|
||||||
|
|
||||||
|
Index: Python-3.14.3/Lib/test/test_poplib.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.14.3.orig/Lib/test/test_poplib.py 2026-02-05 19:22:21.690225015 +0100
|
||||||
|
+++ Python-3.14.3/Lib/test/test_poplib.py 2026-02-05 19:22:24.426584881 +0100
|
||||||
|
@@ -17,6 +17,7 @@
|
||||||
|
from test.support import threading_helper
|
||||||
|
from test.support import asynchat
|
||||||
|
from test.support import asyncore
|
||||||
|
+from test.support import control_characters_c0
|
||||||
|
|
||||||
|
|
||||||
|
test_support.requires_working_socket(module=True)
|
||||||
|
@@ -395,6 +396,13 @@
|
||||||
|
self.assertIsNone(self.client.sock)
|
||||||
|
self.assertIsNone(self.client.file)
|
||||||
|
|
||||||
|
+ def test_control_characters(self):
|
||||||
|
+ for c0 in control_characters_c0():
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ self.client.user(f'user{c0}')
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ self.client.pass_(f'{c0}pass')
|
||||||
|
+
|
||||||
|
@requires_ssl
|
||||||
|
def test_stls_capa(self):
|
||||||
|
capa = self.client.capa()
|
||||||
|
Index: Python-3.14.3/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.14.3/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst 2026-02-05 19:22:24.426813762 +0100
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Reject control characters in POP3 commands.
|
||||||
BIN
Python-3.14.2.tar.xz
LFS
BIN
Python-3.14.2.tar.xz
LFS
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
Python-3.14.3.tar.xz
LFS
Normal file
BIN
Python-3.14.3.tar.xz
LFS
Normal file
Binary file not shown.
1
Python-3.14.3.tar.xz.sigstore
Normal file
1
Python-3.14.3.tar.xz.sigstore
Normal file
File diff suppressed because one or more lines are too long
@@ -1,30 +0,0 @@
|
|||||||
From 4bb41b28d5bac09bccd636d8c5fefe1a462f63a7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alm <alon.menczer@gmail.com>
|
|
||||||
Date: Mon, 25 Aug 2025 08:56:38 +0300
|
|
||||||
Subject: [PATCH 1/4] Exclude .pyc files from the computed digest in the jit
|
|
||||||
stencils
|
|
||||||
|
|
||||||
---
|
|
||||||
Tools/jit/_targets.py | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
Index: Python-3.14.0rc2/Tools/jit/_targets.py
|
|
||||||
===================================================================
|
|
||||||
--- Python-3.14.0rc2.orig/Tools/jit/_targets.py
|
|
||||||
+++ Python-3.14.0rc2/Tools/jit/_targets.py
|
|
||||||
@@ -69,6 +69,9 @@ class _Target(typing.Generic[_S, _R]):
|
|
||||||
hasher.update(PYTHON_EXECUTOR_CASES_C_H.read_bytes())
|
|
||||||
hasher.update((self.pyconfig_dir / "pyconfig.h").read_bytes())
|
|
||||||
for dirpath, _, filenames in sorted(os.walk(TOOLS_JIT)):
|
|
||||||
+ # Exclude cache files from digest computation to ensure reproducible builds.
|
|
||||||
+ if dirpath.endswith("__pycache__"):
|
|
||||||
+ continue
|
|
||||||
for filename in filenames:
|
|
||||||
hasher.update(pathlib.Path(dirpath, filename).read_bytes())
|
|
||||||
return hasher.hexdigest()
|
|
||||||
Index: Python-3.14.0rc2/Misc/NEWS.d/next/Build/2025-08-27-09-52-45.gh-issue-138061.fMVS9w.rst
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ Python-3.14.0rc2/Misc/NEWS.d/next/Build/2025-08-27-09-52-45.gh-issue-138061.fMVS9w.rst
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+Ensure reproducible builds by making JIT stencil header generation deterministic.
|
|
||||||
@@ -7,10 +7,10 @@ Subject: [PATCH 1/2] gh-139257: Support docutils >= 0.22
|
|||||||
Doc/tools/extensions/pyspecific.py | 68 +++++++++++++++++++++++++------------
|
Doc/tools/extensions/pyspecific.py | 68 +++++++++++++++++++++++++------------
|
||||||
1 file changed, 46 insertions(+), 22 deletions(-)
|
1 file changed, 46 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
Index: Python-3.14.2/Doc/tools/extensions/pyspecific.py
|
Index: Python-3.14.3/Doc/tools/extensions/pyspecific.py
|
||||||
===================================================================
|
===================================================================
|
||||||
--- Python-3.14.2.orig/Doc/tools/extensions/pyspecific.py 2025-12-05 17:49:16.000000000 +0100
|
--- Python-3.14.3.orig/Doc/tools/extensions/pyspecific.py 2026-02-03 16:32:20.000000000 +0100
|
||||||
+++ Python-3.14.2/Doc/tools/extensions/pyspecific.py 2025-12-11 18:15:44.936875242 +0100
|
+++ Python-3.14.3/Doc/tools/extensions/pyspecific.py 2026-02-05 16:01:45.363997744 +0100
|
||||||
@@ -1,12 +1,12 @@
|
@@ -1,12 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,3 +1,377 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Feb 5 17:26:23 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2025-12781-b64decode-alt-chars.patch fixing bsc#1257108
|
||||||
|
(CVE-2025-12781) combining gh#python/cpython!141061,
|
||||||
|
gh#python/cpython!141128, and gh#python/cpython!141153. All
|
||||||
|
`*b64decode` functions should not accept non-altchars.
|
||||||
|
- Add CVE-2025-15366-imap-ctrl-chars.patch fixing bsc#1257044
|
||||||
|
(CVE-2025-15366) using gh#python/cpython!143922 and doing
|
||||||
|
basically the same as the previous patch for IMAP protocol.
|
||||||
|
- Add CVE-2025-15367-poplib-ctrl-chars.patch fixing bsc#1257041
|
||||||
|
(CVE-2025-15367) using gh#python/cpython!143924 and doing
|
||||||
|
basically the same as the previous patch for poplib library.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Feb 5 12:57:09 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update to 3.14.3:
|
||||||
|
- Tools/Demos
|
||||||
|
- gh-142095: Make gdb ‘py-bt’ command use frame from thread
|
||||||
|
local state when available. Patch by Sam Gross and Victor
|
||||||
|
Stinner.
|
||||||
|
- Tests
|
||||||
|
- gh-144415: The Android testbed now distinguishes between
|
||||||
|
stdout/stderr messages which were triggered by a newline,
|
||||||
|
and those triggered by a manual call to flush. This fixes
|
||||||
|
logging of progress indicators and similar content.
|
||||||
|
- gh-143460: Skip tests relying on infinite recusion if stack
|
||||||
|
size is unlimited.
|
||||||
|
- gh-65784: Add support for parametrized resource wantobjects
|
||||||
|
in regrtests, which allows to run Tkinter tests with the
|
||||||
|
specified value of tkinter.wantobjects, for example -u
|
||||||
|
wantobjects=0.
|
||||||
|
- gh-143553: Add support for parametrized resources, such as
|
||||||
|
-u xpickle=2.7.
|
||||||
|
- gh-142836: Accommodated Solaris in
|
||||||
|
test_pdb.test_script_target_anonymous_pipe.
|
||||||
|
- bpo-31391: Forward-port test_xpickle from Python 2 to
|
||||||
|
Python 3 and add the resource back to test’s command line.
|
||||||
|
- 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.
|
||||||
|
- 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.
|
||||||
|
- Library
|
||||||
|
- gh-144380: Improve performance of io.BufferedReader line
|
||||||
|
iteration by ~49%.
|
||||||
|
- gh-144169: Fix three crashes when non-string keyword
|
||||||
|
arguments are supplied to objects in the ast module.
|
||||||
|
- gh-144100: Fixed a crash in ctypes when using a deprecated
|
||||||
|
POINTER(str) type in argtypes. Instead of aborting, ctypes
|
||||||
|
now raises a proper Python exception when the pointer
|
||||||
|
target type is unresolved.
|
||||||
|
- gh-144050: Fix stat.filemode() in the pure-Python
|
||||||
|
implementation to avoid misclassifying invalid mode values
|
||||||
|
as block devices.
|
||||||
|
- gh-144023: Fixed validation of file descriptor 0 in posix
|
||||||
|
functions when used with follow_symlinks parameter.
|
||||||
|
- gh-143999: Fix an issue where inspect.getgeneratorstate()
|
||||||
|
and inspect.getcoroutinestate() could fail for generators
|
||||||
|
wrapped by types.coroutine() in the suspended state.
|
||||||
|
- gh-143831: annotationlib.ForwardRef objects are now
|
||||||
|
hashable when created from annotation scopes with closures.
|
||||||
|
Previously, hashing such objects would throw an exception.
|
||||||
|
Patch by Bartosz Sławecki.
|
||||||
|
- gh-143874: Fixed a bug in pdb where expression results were
|
||||||
|
not sent back to remote client.
|
||||||
|
- gh-143880: Fix data race in functools.partial() in the free
|
||||||
|
threading build.
|
||||||
|
- gh-143706: Fix multiprocessing forkserver so that sys.argv
|
||||||
|
is correctly set before __main__ is preloaded. Previously,
|
||||||
|
sys.argv was empty during main module import in forkserver
|
||||||
|
child processes. This fixes a regression introduced in
|
||||||
|
3.13.8 and 3.14.1. Root caused by Aaron Wieczorek, test
|
||||||
|
provided by Thomas Watson, thanks!
|
||||||
|
- gh-143638: Forbid reentrant calls of the pickle.Pickler and
|
||||||
|
pickle.Unpickler methods for the C implementation.
|
||||||
|
Previously, this could cause crash or data corruption, now
|
||||||
|
concurrent calls of methods of the same object raise
|
||||||
|
RuntimeError.
|
||||||
|
- gh-78724: Raise RuntimeError’s when user attempts to call
|
||||||
|
methods on half-initialized Struct objects, For example,
|
||||||
|
created by Struct.__new__(Struct). Patch by Sergey
|
||||||
|
B Kirpichev.
|
||||||
|
- gh-143196: Fix crash when the internal encoder object
|
||||||
|
returned by undocumented function
|
||||||
|
json.encoder.c_make_encoder() was called with non-zero
|
||||||
|
second (_current_indent_level) argument.
|
||||||
|
- gh-143191: _thread.stack_size() now raises ValueError if
|
||||||
|
the stack size is too small. Patch by Victor Stinner.
|
||||||
|
- gh-143602: Fix a inconsistency issue in write() that leads
|
||||||
|
to unexpected buffer overwrite by deduplicating the buffer
|
||||||
|
exports.
|
||||||
|
- gh-143547: Fix sys.unraisablehook() when the hook raises an
|
||||||
|
exception and changes sys.unraisablehook(): hold a strong
|
||||||
|
reference to the old hook. Patch by Victor Stinner.
|
||||||
|
- gh-143517: annotationlib.get_annotations() no longer raises
|
||||||
|
a SyntaxError when evaluating a stringified starred
|
||||||
|
annotation that starts with one or more whitespace
|
||||||
|
characters followed by a *. Patch by Bartosz Sławecki.
|
||||||
|
- gh-143378: Fix use-after-free crashes when a BytesIO object
|
||||||
|
is concurrently mutated during write() or writelines().
|
||||||
|
- gh-143346: Fix incorrect wrapping of the Base64 data in
|
||||||
|
plistlib._PlistWriter when the indent contains a mix of
|
||||||
|
tabs and spaces.
|
||||||
|
- gh-143310: tkinter: fix a crash when a Python list is
|
||||||
|
mutated during the conversion to a Tcl object (e.g., when
|
||||||
|
setting a Tcl variable). Patch by Bénédikt Tran.
|
||||||
|
- gh-143309: Fix a crash in os.execve() on non-Windows
|
||||||
|
platforms when given a custom environment mapping which is
|
||||||
|
then mutated during parsing. Patch by Bénédikt Tran.
|
||||||
|
- gh-143308: pickle: fix use-after-free crashes when
|
||||||
|
a PickleBuffer is concurrently mutated by a custom buffer
|
||||||
|
callback during pickling. Patch by Bénédikt Tran and Aaron
|
||||||
|
Wieczorek.
|
||||||
|
- gh-143237: Fix support of named pipes in the rotating
|
||||||
|
logging handlers.
|
||||||
|
- gh-143249: Fix possible buffer leaks in Windows overlapped
|
||||||
|
I/O on error handling.
|
||||||
|
- gh-143241: zoneinfo: fix infinite loop in
|
||||||
|
ZoneInfo.from_file when parsing a malformed TZif file.
|
||||||
|
Patch by Fatih Celik.
|
||||||
|
- gh-142830: sqlite3: fix use-after-free crashes when the
|
||||||
|
connection’s callbacks are mutated during a callback
|
||||||
|
execution. Patch by Bénédikt Tran.
|
||||||
|
- gh-143200: xml.etree.ElementTree: fix use-after-free
|
||||||
|
crashes in __getitem__() and __setitem__() methods of
|
||||||
|
Element when the element is concurrently mutated. Patch by
|
||||||
|
Bénédikt Tran.
|
||||||
|
- gh-142195: Updated timeout evaluation logic in subprocess
|
||||||
|
to be compatible with deterministic environments like
|
||||||
|
Shadow where time moves exactly as requested.
|
||||||
|
- gh-142164: Fix the ctypes bitfield overflow error message
|
||||||
|
to report the correct offset and size calculation.
|
||||||
|
- gh-143145: Fixed a possible reference leak in ctypes when
|
||||||
|
constructing results with multiple output parameters on
|
||||||
|
error.
|
||||||
|
- gh-122431: Corrected the error message in
|
||||||
|
readline.append_history_file() to state that nelements must
|
||||||
|
be non-negative instead of positive.
|
||||||
|
- gh-143004: Fix a potential use-after-free in
|
||||||
|
collections.Counter.update() when user code mutates the
|
||||||
|
Counter during an update.
|
||||||
|
- gh-143046: The asyncio REPL no longer prints copyright and
|
||||||
|
version messages in the quiet mode (-q). Patch by Bartosz
|
||||||
|
Sławecki.
|
||||||
|
- gh-140648: The asyncio REPL now respects the -I flag
|
||||||
|
(isolated mode). Previously, it would load and execute
|
||||||
|
PYTHONSTARTUP even if the flag was set. Contributed by
|
||||||
|
Bartosz Sławecki.
|
||||||
|
- gh-142991: Fixed socket operations such as recvfrom() and
|
||||||
|
sendto() for FreeBSD divert(4) socket.
|
||||||
|
- gh-143010: Fixed a bug in mailbox where the precise timing
|
||||||
|
of an external event could result in the library opening an
|
||||||
|
existing file instead of a file it expected to create.
|
||||||
|
- gh-142881: Fix concurrent and reentrant call of
|
||||||
|
atexit.unregister().
|
||||||
|
- gh-112127: Fix possible use-after-free in
|
||||||
|
atexit.unregister() when the callback is unregistered
|
||||||
|
during comparison.
|
||||||
|
- gh-142783: Fix zoneinfo use-after-free with descriptor
|
||||||
|
_weak_cache. a descriptor as _weak_cache could cause
|
||||||
|
crashes during object creation. The fix ensures proper
|
||||||
|
reference counting for descriptor-provided objects.
|
||||||
|
- gh-142754: 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.
|
||||||
|
- gh-142784: The asyncio REPL now properly closes the loop
|
||||||
|
upon the end of interactive session. Previously, it could
|
||||||
|
cause surprising warnings. Contributed by Bartosz Sławecki.
|
||||||
|
- gh-142555: array: fix a crash in a[i] = v when converting
|
||||||
|
i to an index via i.__index__ or i.__float__ mutates the
|
||||||
|
array.
|
||||||
|
- gh-142594: Fix crash in TextIOWrapper.close() when the
|
||||||
|
underlying buffer’s closed property calls detach().
|
||||||
|
- gh-142451: hmac: Ensure that the HMAC.block_size attribute
|
||||||
|
is correctly copied by HMAC.copy. Patch by Bénédikt Tran.
|
||||||
|
- gh-142495: collections.defaultdict now prioritizes
|
||||||
|
__setitem__() when inserting default values from
|
||||||
|
default_factory. This prevents race conditions where
|
||||||
|
a default value would overwrite a value set before
|
||||||
|
default_factory returns.
|
||||||
|
- gh-142651: unittest.mock: fix a thread safety issue where
|
||||||
|
Mock.call_count may return inaccurate values when the mock
|
||||||
|
is called concurrently from multiple threads.
|
||||||
|
- gh-142595: Added type check during initialization of the
|
||||||
|
decimal module to prevent a crash in case of broken stdlib.
|
||||||
|
Patch by Sergey B Kirpichev.
|
||||||
|
- gh-142556: Fix crash when a task gets re-registered during
|
||||||
|
finalization in asyncio. Patch by Kumar Aditya.
|
||||||
|
- gh-123241: Avoid reference count operations in garbage
|
||||||
|
collection of ctypes objects.
|
||||||
|
- gh-142517: The non-compat32 email policies now correctly
|
||||||
|
handle refolding encoded words that contain bytes that can
|
||||||
|
not be decoded in their specified character set. Previously
|
||||||
|
this resulted in an encoding exception during folding.
|
||||||
|
- gh-112527: The help text for required options in argparse
|
||||||
|
no longer extended with “ (default: None)”.
|
||||||
|
- gh-142346: Fix usage formatting for mutually exclusive
|
||||||
|
groups in argparse when they are preceded by positional
|
||||||
|
arguments or followed or intermixed with other optional
|
||||||
|
arguments.
|
||||||
|
- gh-142315: Pdb can now run scripts from anonymous pipes
|
||||||
|
used in process substitution. Patch by Bartosz Sławecki.
|
||||||
|
- gh-142332: Fix usage formatting for positional arguments in
|
||||||
|
mutually exclusive groups in argparse. in argparse.
|
||||||
|
- gh-142282: Fix winreg.QueryValueEx() to not accidentally
|
||||||
|
read garbage buffer under race condition.
|
||||||
|
- gh-75949: Fix argparse to preserve | separators in mutually
|
||||||
|
exclusive groups when the usage line wraps due to length.
|
||||||
|
- gh-142267: Improve argparse performance by caching the
|
||||||
|
formatter used for argument validation.
|
||||||
|
- gh-68552: MisplacedEnvelopeHeaderDefect and Missing header
|
||||||
|
name defects are now correctly passed to the handle_defect
|
||||||
|
method of policy in FeedParser.
|
||||||
|
- gh-142006: Fix a bug in the email.policy.default folding
|
||||||
|
algorithm which incorrectly resulted in a doubled newline
|
||||||
|
when a line ending at exactly max_line_length was followed
|
||||||
|
by an unfoldable token.
|
||||||
|
- gh-105836: Fix asyncio.run_coroutine_threadsafe() leaving
|
||||||
|
underlying cancelled asyncio task running.
|
||||||
|
- gh-139971: pydoc: Ensure that the link to the online
|
||||||
|
documentation of a stdlib module is correct.
|
||||||
|
- gh-139262: Some keystrokes can be swallowed in the new
|
||||||
|
PyREPL on Windows, especially when used together with the
|
||||||
|
ALT key. Fix by Chris Eibl.
|
||||||
|
- gh-138897: Improved license/copyright/credits display in
|
||||||
|
the REPL: now uses a pager.
|
||||||
|
- gh-79986: Add parsing for References and In-Reply-To
|
||||||
|
headers to the email library that parses the header content
|
||||||
|
as lists of message id tokens. This prevents them from
|
||||||
|
being folded incorrectly.
|
||||||
|
- gh-136282: Add support for UNNAMED_SECTION when creating
|
||||||
|
a section via the mapping protocol access
|
||||||
|
- gh-109263: Starting a process from spawn context in
|
||||||
|
multiprocessing no longer sets the start method globally.
|
||||||
|
- gh-133253: Fix thread-safety issues in linecache.
|
||||||
|
- gh-132715: Skip writing objects during marshalling once
|
||||||
|
a failure has occurred.
|
||||||
|
- IDLE
|
||||||
|
- gh-143774: Better explain the operation of Format / Format
|
||||||
|
Paragraph.
|
||||||
|
- Documentation
|
||||||
|
- gh-140806: Add documentation for enum.bin().
|
||||||
|
- Core and Builtins
|
||||||
|
- gh-144307: Prevent a reference leak in module teardown at
|
||||||
|
interpreter finalization.
|
||||||
|
- gh-144194: Fix error handling in perf jitdump
|
||||||
|
initialization on memory allocation failure.
|
||||||
|
- gh-144012: Check if the result is NULL in BINARY_OP_EXTENT
|
||||||
|
opcode.
|
||||||
|
- gh-141805: Fix crash in set when objects with the same hash
|
||||||
|
are concurrently added to the set after removing an element
|
||||||
|
with the same hash while the set still contains elements
|
||||||
|
with the same hash.
|
||||||
|
- gh-143670: Fixes a crash in ga_repr_items_list function.
|
||||||
|
- gh-143377: Fix a crash in _interpreters.capture_exception()
|
||||||
|
when the exception is incorrectly formatted. Patch by
|
||||||
|
Bénédikt Tran.
|
||||||
|
- gh-136924: The interactive help mode in the REPL no longer
|
||||||
|
incorrectly syntax highlights text input as Python code.
|
||||||
|
Contributed by Olga Matoula.
|
||||||
|
- gh-143189: Fix crash when inserting a non-str key into
|
||||||
|
a split table dictionary when the key matches an existing
|
||||||
|
key in the split table but has no corresponding value in
|
||||||
|
the dict.
|
||||||
|
- gh-143228: Fix use-after-free in perf trampoline when
|
||||||
|
toggling profiling while threads are running or during
|
||||||
|
interpreter finalization with daemon threads active. The
|
||||||
|
fix uses reference counting to ensure trampolines are not
|
||||||
|
freed while any code object could still reference them.
|
||||||
|
Pach by Pablo Galindo
|
||||||
|
- gh-142664: Fix a use-after-free crash in
|
||||||
|
memoryview.__hash__ when the __hash__ method of the
|
||||||
|
referenced object mutates that object or the view. Patch by
|
||||||
|
Bénédikt Tran.
|
||||||
|
- gh-142557: Fix a use-after-free crash in bytearray.__mod__
|
||||||
|
when the bytearray is mutated while formatting the %-style
|
||||||
|
arguments. Patch by Bénédikt Tran.
|
||||||
|
- gh-143195: Fix use-after-free crashes in bytearray.hex()
|
||||||
|
and memoryview.hex() when the separator’s __len__() mutates
|
||||||
|
the original object. Patch by Bénédikt Tran.
|
||||||
|
- gh-142975: Fix crash after unfreezing all objects tracked
|
||||||
|
by the garbage collector on the free threaded build.
|
||||||
|
- gh-143135: Set sys.flags.inspect to 1 when PYTHONINSPECT is
|
||||||
|
0. Previously, it was set to 0 in this case.
|
||||||
|
- gh-143003: Fix an overflow of the shared empty buffer in
|
||||||
|
bytearray.extend() when __length_hint__() returns 0 for
|
||||||
|
non-empty iterator.
|
||||||
|
- gh-143006: Fix a possible assertion error when comparing
|
||||||
|
negative non-integer float and int with the same number of
|
||||||
|
bits in the integer part.
|
||||||
|
- gh-143057: Avoid locking in PyTraceMalloc_Track() and
|
||||||
|
PyTraceMalloc_Untrack() when tracemalloc is not enabled.
|
||||||
|
- gh-142776: Fix a file descriptor leak in import.c
|
||||||
|
- gh-142829: Fix a use-after-free crash in
|
||||||
|
contextvars.Context comparison when a custom __eq__ method
|
||||||
|
modifies the context via set().
|
||||||
|
- gh-142766: Clear the frame of a generator when
|
||||||
|
generator.close() is called.
|
||||||
|
- gh-142737: Tracebacks will be displayed in fallback mode
|
||||||
|
even if io.open() is lost. Previously, this would crash the
|
||||||
|
interpreter. Patch by Bartosz Sławecki.
|
||||||
|
- gh-142554: Fix a crash in divmod() when
|
||||||
|
_pylong.int_divmod() does not return a tuple of length two
|
||||||
|
exactly. Patch by Bénédikt Tran.
|
||||||
|
- gh-142560: Fix use-after-free in bytearray search-like
|
||||||
|
methods (find(), count(), index(), rindex(), and rfind())
|
||||||
|
by marking the storage as exported which causes
|
||||||
|
reallocation attempts to raise BufferError. For contains(),
|
||||||
|
split(), and rsplit() the buffer protocol is used for this.
|
||||||
|
- gh-142531: Fix a free-threaded GC performance regression.
|
||||||
|
If there are many untracked tuples, the GC will run too
|
||||||
|
often, resulting in poor performance. The fix is to include
|
||||||
|
untracked tuples in the “long lived” object count. The
|
||||||
|
number of frozen objects is also now included since the
|
||||||
|
free-threaded GC must scan those too.
|
||||||
|
- gh-142402: Fix reference counting when adjacent literal
|
||||||
|
parts are merged while constructing
|
||||||
|
string.templatelib.Template, preventing the displaced
|
||||||
|
string object from leaking.
|
||||||
|
- gh-133932: Fix crash in the free threading build when
|
||||||
|
clearing frames that hold tagged integers.
|
||||||
|
- gh-142343: Fix SIGILL crash on m68k due to incorrect
|
||||||
|
assembly constraint.
|
||||||
|
- gh-100964: Fix reference cycle in exhausted generator
|
||||||
|
frames. Patch by Savannah Ostrowski.
|
||||||
|
- gh-69605: Fix edge-cases around already imported modules in
|
||||||
|
the REPL auto-completion of imports.
|
||||||
|
- gh-138568: Adjusted the built-in help() function so that
|
||||||
|
empty inputs are ignored in interactive mode.
|
||||||
|
- gh-137007: Fix a bug during JIT compilation failure which
|
||||||
|
caused garbage collection debug assertions to fail.
|
||||||
|
- C API
|
||||||
|
- gh-142589: Fix
|
||||||
|
PyUnstable_Object_IsUniqueReferencedTemporary() handling of
|
||||||
|
tagged ints on the interpreter stack.
|
||||||
|
- gh-142571: PyUnstable_CopyPerfMapFile() now checks that
|
||||||
|
opening the file succeeded before flushing.
|
||||||
|
- Build
|
||||||
|
- gh-142454: When calculating the digest of the JIT stencils
|
||||||
|
input, sort the hashed files by filenames before adding
|
||||||
|
their content to the hasher. This ensures deterministic
|
||||||
|
hash input and hence deterministic hash, independent on
|
||||||
|
filesystem order.
|
||||||
|
- gh-141808: When running make clean-retain-profile, keep the
|
||||||
|
generated JIT stencils. That way, the stencils are not
|
||||||
|
generated twice when Profile-guided optimization (PGO) is
|
||||||
|
used. It also allows distributors to supply their own
|
||||||
|
pre-built JIT stencils.
|
||||||
|
- gh-138061: Ensure reproducible builds by making JIT stencil
|
||||||
|
header generation deterministic.
|
||||||
|
- Remove upstreamed patches:
|
||||||
|
- CVE-2024-6923-follow-up-EOL-email-headers.patch
|
||||||
|
- CVE-2025-11468-email-hdr-fold-comment.patch
|
||||||
|
- CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
|
||||||
|
- gh138131-exclude-pycache-from-digest.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Jan 29 12:58:15 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
Thu Jan 29 12:58:15 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
@@ -7,6 +381,9 @@ Thu Jan 29 12:58:15 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
|||||||
- Add CVE-2025-11468-email-hdr-fold-comment.patch preserving
|
- Add CVE-2025-11468-email-hdr-fold-comment.patch preserving
|
||||||
parens when folding comments in email headers (bsc#1257029,
|
parens when folding comments in email headers (bsc#1257029,
|
||||||
CVE-2025-11468).
|
CVE-2025-11468).
|
||||||
|
- Add CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch, which
|
||||||
|
rejects control characters in http cookies (bsc#1257031,
|
||||||
|
CVE-2026-0672).
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Dec 11 17:37:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
Thu Dec 11 17:37:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
@@ -4027,7 +4404,7 @@ Tue Nov 19 22:08:24 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
|||||||
generated URLs beginning with four slashes (rather than
|
generated URLs beginning with four slashes (rather than
|
||||||
two) when given a Windows UNC path.
|
two) when given a Windows UNC path.
|
||||||
- gh-126156: Improved performances of creating Morsel objects
|
- gh-126156: Improved performances of creating Morsel objects
|
||||||
by a factor of 3.8x.
|
by a factor of 3.8x (bsc#1257031, CVE-2026-0672).
|
||||||
- gh-126105: Fix a crash in ast when the ast.AST._fields
|
- gh-126105: Fix a crash in ast when the ast.AST._fields
|
||||||
attribute is deleted.
|
attribute is deleted.
|
||||||
- gh-126106: Fixes a possible NULL pointer dereference in
|
- gh-126106: Fixes a possible NULL pointer dereference in
|
||||||
|
|||||||
@@ -124,7 +124,7 @@
|
|||||||
# %%define tarversion %%{version}
|
# %%define tarversion %%{version}
|
||||||
# %%endif
|
# %%endif
|
||||||
# We don't process beta signs well
|
# We don't process beta signs well
|
||||||
%define folderversion 3.14.2
|
%define folderversion 3.14.3
|
||||||
%define sitedir %{_libdir}/python%{python_version}
|
%define sitedir %{_libdir}/python%{python_version}
|
||||||
# three possible ABI kinds: m - pymalloc, d - debug build; see PEP 3149
|
# three possible ABI kinds: m - pymalloc, d - debug build; see PEP 3149
|
||||||
%define abi_kind %{nil}
|
%define abi_kind %{nil}
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
# _md5.cpython-38m-x86_64-linux-gnu.so
|
# _md5.cpython-38m-x86_64-linux-gnu.so
|
||||||
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
||||||
Name: %{python_pkg_name}%{psuffix}
|
Name: %{python_pkg_name}%{psuffix}
|
||||||
Version: 3.14.2
|
Version: 3.14.3
|
||||||
%define tarversion %{version}
|
%define tarversion %{version}
|
||||||
%define tarname Python-%{tarversion}
|
%define tarname Python-%{tarversion}
|
||||||
Release: 0
|
Release: 0
|
||||||
@@ -220,17 +220,17 @@ Patch40: fix-test-recursion-limit-15.6.patch
|
|||||||
# PATCH-FIX-UPSTREAM bsc1243155-sphinx-non-determinism.patch bsc#1243155 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM bsc1243155-sphinx-non-determinism.patch bsc#1243155 mcepl@suse.com
|
||||||
# Doc: Generate ids for audit_events using docname
|
# Doc: Generate ids for audit_events using docname
|
||||||
Patch41: bsc1243155-sphinx-non-determinism.patch
|
Patch41: bsc1243155-sphinx-non-determinism.patch
|
||||||
# PATCH-FIX-UPSTREAM gh138131-exclude-pycache-from-digest.patch bsc#1244680 daniel.garcia@suse.com
|
|
||||||
Patch44: gh138131-exclude-pycache-from-digest.patch
|
|
||||||
# PATCH-FIX-OPENSUSE gh139257-Support-docutils-0.22.patch gh#python/cpython#139257 daniel.garcia@suse.com
|
# PATCH-FIX-OPENSUSE gh139257-Support-docutils-0.22.patch gh#python/cpython#139257 daniel.garcia@suse.com
|
||||||
Patch45: gh139257-Support-docutils-0.22.patch
|
Patch45: gh139257-Support-docutils-0.22.patch
|
||||||
# PATCH-FIX-UPSTREAM CVE-2024-6923-follow-up-EOL-email-headers.patch bsc#1257181 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM CVE-2025-12781-b64decode-alt-chars.patch bsc#1257108 mcepl@suse.com
|
||||||
# Encode newlines in headers when using ByteGenerator
|
# Fix decoding with non-standard Base64 alphabet gh#python/cpython#125346
|
||||||
# patch from gh#python/cpython#144125
|
Patch46: CVE-2025-12781-b64decode-alt-chars.patch
|
||||||
Patch46: CVE-2024-6923-follow-up-EOL-email-headers.patch
|
# PATCH-FIX-UPSTREAM CVE-2025-15366-imap-ctrl-chars.patch bsc#1257044 mcepl@suse.com
|
||||||
# PATCH-FIX-UPSTREAM CVE-2025-11468-email-hdr-fold-comment.patch bsc#1257029 mcepl@suse.com
|
# Reject control characters in wsgiref.headers.Headers
|
||||||
# Email preserve parens when folding comments
|
Patch47: CVE-2025-15366-imap-ctrl-chars.patch
|
||||||
Patch47: CVE-2025-11468-email-hdr-fold-comment.patch
|
# PATCH-FIX-UPSTREAM CVE-2025-15367-poplib-ctrl-chars.patch bsc#1257041 mcepl@suse.com
|
||||||
|
# Reject control characters in poplib
|
||||||
|
Patch48: CVE-2025-15367-poplib-ctrl-chars.patch
|
||||||
#### Python 3.14 END OF PATCHES
|
#### Python 3.14 END OF PATCHES
|
||||||
BuildRequires: autoconf-archive
|
BuildRequires: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
|
|||||||
Reference in New Issue
Block a user