6 Commits

Author SHA256 Message Date
d7ebe63704 Update to 3.11.15:
- Security
    - gh-144125: BytesGenerator will now refuse to serialize
      (write) headers that are unsafely folded or delimited; see
      verify_generated_headers. (Contributed by Bas Bloemsaat and
      Petr Viktorin in gh-121650).
    - gh-143935: Fixed a bug in the folding of comments when
      flattening an email message using a modern email policy.
      Comments consisting of a very long sequence of non-foldable
      characters could trigger a forced line wrap that omitted
      the required leading space on the continuation line,
      causing the remainder of the comment to be interpreted as
      a new header field. This enabled header injection with
      carefully crafted inputs (bsc#1257029 CVE-2025-11468).
    - gh-143925: Reject control characters in data: URL media
      types (bsc#1257046, CVE-2025-15282).
    - gh-143919: Reject control characters in http.cookies.Morsel
      fields and values (bsc#1257031, CVE-2026-0672).
    - gh-143916: Reject C0 control characters within
      wsgiref.headers.Headers fields, values, and parameters
      (bsc#1257042, CVE-2026-0865).
    - gh-142145: Remove quadratic behavior in xml.minidom node ID
      cache clearing. In order to do this without breaking
      existing users, we also add the ownerDocument attribute to
      xml.dom.minidom elements and attributes created by directly
      instantiating the Element or Attr class. Note that this way
      of creating nodes is not supported; creator functions like
      xml.dom.Document.documentElement() should be used instead
      (bsc#1254997, CVE-2025-12084).
    - gh-137836: Add support of the “plaintext” element, RAWTEXT
      elements “xmp”, “iframe”, “noembed” and “noframes”, and
      optionally RAWTEXT element “noscript” in
      html.parser.HTMLParser.
    - gh-136063: email.message: ensure linear complexity for
      legacy HTTP parameters parsing. Patch by Bénédikt Tran.
    - gh-136065: Fix quadratic complexity in
      os.path.expandvars() (bsc#1252974, CVE-2025-6075).
    - gh-119451: Fix a potential memory denial of service in the
      http.client module. When connecting to a malicious server,
      it could cause an arbitrary amount of memory to be
      allocated. This could have led to symptoms including
      a MemoryError, swapping, out of memory (OOM) killed
      processes or containers, or even system crashes
      (CVE-2025-13836, bsc#1254400).
    - gh-119452: Fix a potential memory denial of service in the
      http.server module. When a malicious user is connected to
      the CGI server on Windows, it could cause an arbitrary
      amount of memory to be allocated. This could have led to
      symptoms including a MemoryError, swapping, out of memory
      (OOM) killed processes or containers, or even system
      crashes.
    - gh-119342: Fix a potential memory denial of service in the
      plistlib module. When reading a Plist file received from
      untrusted source, it could cause an arbitrary amount of
      memory to be allocated. This could have led to symptoms
      including a MemoryError, swapping, out of memory (OOM)
      killed processes or containers, or even system crashes
      (bsc#1254401, CVE-2025-13837).
  - Library
    - gh-144833: Fixed a use-after-free in ssl when SSL_new()
      returns NULL in newPySSLSocket(). The error was reported
      via a dangling pointer after the object had already been
      freed.
    - gh-144363: Update bundled libexpat to 2.7.4
    - gh-90949: Add SetAllocTrackerActivationThreshold() and
      SetAllocTrackerMaximumAmplification() to xmlparser objects
      to prevent use of disproportional amounts of dynamic memory
      from within an Expat parser. Patch by Bénédikt Tran.
  - Core and Builtins
    - gh-120384: Fix an array out of bounds crash in
      list_ass_subscript, which could be invoked via some
      specificly tailored input: including concurrent
      modification of a list object, where one thread assigns
      a slice and another clears it.
    - gh-120298: Fix use-after free in list_richcompare_impl
      which can be invoked via some specificly tailored evil
      input.
Remove upstreamed patches:
  - CVE-2025-11468-email-hdr-fold-comment.patch
  - CVE-2025-12084-minidom-quad-search.patch
  - CVE-2025-13836-http-resp-cont-len.patch
  - CVE-2025-13837-plistlib-mailicious-length.patch
  - CVE-2025-6075-expandvars-perf-degrad.patch
  - CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
  - CVE-2026-0865-wsgiref-ctrl-chars.patch
  - CVE-2025-15282-urllib-ctrl-chars.patch
2026-03-09 00:26:16 +01:00
26a31005ec Merge branch 'factory' into sle-15-sp4 2026-02-24 09:14:57 +01:00
02f09793e7 Fix seven CVEs
CVE-2025-11468: preserving parens when folding comments in
  email headers (bsc#1257029, gh#python/cpython#143935).
  CVE-2025-11468-email-hdr-fold-comment.patch
CVE-2026-0672: rejects control characters in http cookies.
  (bsc#1257031, gh#python/cpython#143919)
  CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
CVE-2026-0865: rejecting control characters in
  wsgiref.headers.Headers, which could be abused for injecting
  false HTTP headers. (bsc#1257042, gh#python/cpython#143916)
  CVE-2026-0865-wsgiref-ctrl-chars.patch
CVE-2025-15366: basically the same as the previous patch for
  IMAP protocol. (bsc#1257044, gh#python/cpython#143921)
  CVE-2025-15366-imap-ctrl-chars.patch
CVE-2025-15282: basically the same as the previous patch for
  urllib library. (bsc#1257046, gh#python/cpython#143925)
  CVE-2025-15282-urllib-ctrl-chars.patch
CVE-2025-15367: basically the same as the previous patch for
  poplib library. (bsc#1257041, gh#python/cpython#143923)
  CVE-2025-15367-poplib-ctrl-chars.patch
CVE-2025-12781: fix decoding with non-standard Base64 alphabet
  (bsc#1257108, gh#python/cpython#125346)
  CVE-2025-12781-b64decode-alt-chars.patch
2026-02-13 00:45:50 +01:00
cd09787966 Fix CVE-2025-13836, CVE-2025-12084, and CVE-2025-13837.
- Add CVE-2025-13836-http-resp-cont-len.patch (bsc#1254400,
  CVE-2025-13836) to prevent reading an HTTP response from
  a server, if no read amount is specified, with using
  Content-Length per default as the length.
- Add CVE-2025-12084-minidom-quad-search.patch prevent quadratic
  behavior in node ID cache clearing (CVE-2025-12084,
  bsc#1254997).
- Add CVE-2025-13837-plistlib-mailicious-length.patch protect
  against OOM when loading malicious content (CVE-2025-13837,
  bsc#1254401).
2026-01-08 13:42:27 +01:00
162a9695a4 Fix CVE-2025-13836, CVE-2025-12084, and CVE-2025-13837.
- Add CVE-2025-13836-http-resp-cont-len.patch (bsc#1254400,
  CVE-2025-13836) to prevent reading an HTTP response from
  a server, if no read amount is specified, with using
  Content-Length per default as the length.
- Add CVE-2025-12084-minidom-quad-search.patch prevent quadratic
  behavior in node ID cache clearing (CVE-2025-12084,
  bsc#1254997).
- Add CVE-2025-13837-plistlib-mailicious-length.patch protect
  against OOM when loading malicious content (CVE-2025-13837,
  bsc#1254401).
2025-12-19 23:09:22 +01:00
48953809e4 Add CVE-2025-6075-expandvars-perf-degrad.patch
Avoid simple quadratic complexity vulnerabilities of os.path.expandvars()
  (CVE-2025-6075, bsc#1252974).
Readjusted patches:
  - CVE-2023-52425-libexpat-2.6.0-backport.patch
  - CVE-2023-52425-remove-reparse_deferral-tests.patch
  - fix_configure_rst.patch
  - skip_if_buildbot-extend.patch
2025-11-20 23:16:35 +01:00
14 changed files with 503 additions and 422 deletions

View File

@@ -1,15 +1,15 @@
---
Lib/test/support/__init__.py | 16 ++++++++++++++--
Lib/test/support/__init__.py | 22 ++++++++++++++++------
Lib/test/test_minidom.py | 23 +++++++++--------------
Lib/test/test_pyexpat.py | 12 +++++-------
Lib/test/test_sax.py | 18 +++++++++---------
Lib/test/test_xml_etree.py | 12 ------------
5 files changed, 37 insertions(+), 44 deletions(-)
5 files changed, 39 insertions(+), 48 deletions(-)
Index: Python-3.11.14/Lib/test/support/__init__.py
Index: Python-3.11.15/Lib/test/support/__init__.py
===================================================================
--- Python-3.11.14.orig/Lib/test/support/__init__.py 2025-11-15 19:15:08.449938538 +0100
+++ Python-3.11.14/Lib/test/support/__init__.py 2025-11-15 19:15:12.859120260 +0100
--- Python-3.11.15.orig/Lib/test/support/__init__.py 2026-03-09 00:22:05.833623479 +0100
+++ Python-3.11.15/Lib/test/support/__init__.py 2026-03-09 00:25:45.751482485 +0100
@@ -8,6 +8,7 @@
import functools
import os
@@ -18,7 +18,7 @@ Index: Python-3.11.14/Lib/test/support/__init__.py
import stat
import sys
import sysconfig
@@ -56,7 +57,7 @@
@@ -56,10 +57,9 @@
"run_with_tz", "PGO", "missing_compiler_executable",
"ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
"LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
@@ -26,39 +26,48 @@ Index: Python-3.11.14/Lib/test/support/__init__.py
+ "skip_on_s390x", "fails_with_expat_2_6_0", "is_expat_2_6_0"
]
@@ -2279,6 +2280,17 @@
-
# Timeout in seconds for tests using a network server listening on the network
# local loopback interface like 127.0.0.1.
#
@@ -2279,10 +2279,20 @@
}
return ignored
-#Windows doesn't have os.uname() but it doesn't support s390x.
+
-skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
- 'skipped on s390x')
-
+# Windows doesn't have os.uname() but it doesn't support s390x.
skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
'skipped on s390x')
+
+skip_on_s390x = unittest.skipIf(
+ hasattr(os, 'uname') and os.uname().machine == 's390x',
+ 'skipped on s390x')
+
+@functools.lru_cache
+def _is_expat_2_6_0():
+ return hasattr(pyexpat.ParserCreate(), 'SetReparseDeferralEnabled')
+
+is_expat_2_6_0 = _is_expat_2_6_0()
+
+fails_with_expat_2_6_0 = (unittest.expectedFailure
+ if is_expat_2_6_0
+ else lambda test: test)
Index: Python-3.11.14/Lib/test/test_minidom.py
def control_characters_c0() -> list[str]:
"""Returns a list of C0 control characters as strings.
Index: Python-3.11.15/Lib/test/test_minidom.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_minidom.py 2025-11-15 19:14:53.915952608 +0100
+++ Python-3.11.14/Lib/test/test_minidom.py 2025-11-15 19:15:12.859877278 +0100
@@ -6,7 +6,6 @@
--- Python-3.11.15.orig/Lib/test/test_minidom.py 2026-03-09 00:22:01.870138109 +0100
+++ Python-3.11.15/Lib/test/test_minidom.py 2026-03-09 00:22:05.864561664 +0100
@@ -7,7 +7,6 @@
from test import support
import unittest
-import pyexpat
import xml.dom.minidom
from xml.dom.minidom import parse, Attr, Node, Document, parseString
@@ -1163,13 +1162,11 @@
from xml.dom.minidom import parse, Attr, Node, Document, Element, parseString
@@ -1194,13 +1193,11 @@
# Verify that character decoding errors raise exceptions instead
# of crashing
@@ -77,7 +86,7 @@ Index: Python-3.11.14/Lib/test/test_minidom.py
b'<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
doc.unlink()
@@ -1631,12 +1628,10 @@
@@ -1662,12 +1659,10 @@
self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)
def testExceptionOnSpacesInXMLNSValue(self):
@@ -94,11 +103,11 @@ Index: Python-3.11.14/Lib/test/test_minidom.py
parseString('<element xmlns:abc="http:abc.com/de f g/hi/j k"><abc:foo /></element>')
def testDocRemoveChild(self):
Index: Python-3.11.14/Lib/test/test_pyexpat.py
Index: Python-3.11.15/Lib/test/test_pyexpat.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_pyexpat.py 2025-11-15 19:14:53.915952608 +0100
+++ Python-3.11.14/Lib/test/test_pyexpat.py 2025-11-15 19:15:12.860334045 +0100
@@ -14,8 +14,7 @@
--- Python-3.11.15.orig/Lib/test/test_pyexpat.py 2026-03-09 00:22:02.085337730 +0100
+++ Python-3.11.15/Lib/test/test_pyexpat.py 2026-03-09 00:22:21.434819111 +0100
@@ -18,8 +18,7 @@
from xml.parsers import expat
from xml.parsers.expat import errors
@@ -108,7 +117,7 @@ Index: Python-3.11.14/Lib/test/test_pyexpat.py
class SetAttributeTest(unittest.TestCase):
def setUp(self):
@@ -806,9 +805,8 @@
@@ -810,9 +809,8 @@
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
def test_reparse_deferral_enabled(self):
@@ -120,7 +129,7 @@ Index: Python-3.11.14/Lib/test/test_pyexpat.py
started = []
@@ -837,9 +835,9 @@
@@ -841,9 +839,9 @@
parser = expat.ParserCreate()
parser.StartElementHandler = start_element
@@ -132,10 +141,10 @@ Index: Python-3.11.14/Lib/test/test_pyexpat.py
for chunk in (b'<doc', b'/>'):
parser.Parse(chunk, False)
Index: Python-3.11.14/Lib/test/test_sax.py
Index: Python-3.11.15/Lib/test/test_sax.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_sax.py 2025-11-15 19:14:53.915952608 +0100
+++ Python-3.11.14/Lib/test/test_sax.py 2025-11-15 19:15:12.860746114 +0100
--- Python-3.11.15.orig/Lib/test/test_sax.py 2026-03-09 00:22:02.128712585 +0100
+++ Python-3.11.15/Lib/test/test_sax.py 2026-03-09 00:22:21.434819111 +0100
@@ -19,13 +19,11 @@
from io import BytesIO, StringIO
import codecs
@@ -187,10 +196,10 @@ Index: Python-3.11.14/Lib/test/test_sax.py
self.assertFalse(parser._parser.GetReparseDeferralEnabled())
Index: Python-3.11.14/Lib/test/test_xml_etree.py
Index: Python-3.11.15/Lib/test/test_xml_etree.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_xml_etree.py 2025-11-15 19:14:53.915952608 +0100
+++ Python-3.11.14/Lib/test/test_xml_etree.py 2025-11-15 19:15:12.861491049 +0100
--- Python-3.11.15.orig/Lib/test/test_xml_etree.py 2026-03-09 00:22:02.529714798 +0100
+++ Python-3.11.15/Lib/test/test_xml_etree.py 2026-03-09 00:22:21.434819111 +0100
@@ -13,7 +13,6 @@
import operator
import os

View File

@@ -4,11 +4,11 @@
Lib/test/test_xml_etree.py | 2 ++
3 files changed, 6 insertions(+)
Index: Python-3.11.14/Lib/test/test_pyexpat.py
Index: Python-3.11.15/Lib/test/test_pyexpat.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_pyexpat.py 2025-11-15 19:15:12.860334045 +0100
+++ Python-3.11.14/Lib/test/test_pyexpat.py 2025-11-15 19:15:15.541090355 +0100
@@ -804,6 +804,7 @@
--- Python-3.11.15.orig/Lib/test/test_pyexpat.py 2026-03-06 16:07:07.713428031 +0100
+++ Python-3.11.15/Lib/test/test_pyexpat.py 2026-03-06 18:23:34.307976750 +0100
@@ -808,6 +808,7 @@
parser.SetReparseDeferralEnabled(True)
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
@@ -16,7 +16,7 @@ Index: Python-3.11.14/Lib/test/test_pyexpat.py
def test_reparse_deferral_enabled(self):
if not is_expat_2_6_0:
self.skipTest("Linked libexpat doesn't support reparse deferral")
@@ -827,6 +828,7 @@
@@ -831,6 +832,7 @@
self.assertEqual(started, ['doc'])
@@ -24,10 +24,10 @@ Index: Python-3.11.14/Lib/test/test_pyexpat.py
def test_reparse_deferral_disabled(self):
started = []
Index: Python-3.11.14/Lib/test/test_sax.py
Index: Python-3.11.15/Lib/test/test_sax.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_sax.py 2025-11-15 19:15:12.860746114 +0100
+++ Python-3.11.14/Lib/test/test_sax.py 2025-11-15 19:15:15.541608234 +0100
--- Python-3.11.15.orig/Lib/test/test_sax.py 2026-03-06 16:07:07.713855947 +0100
+++ Python-3.11.15/Lib/test/test_sax.py 2026-03-06 18:23:34.309155833 +0100
@@ -1213,6 +1213,7 @@
self.assertEqual(result.getvalue(), start + b"<doc>text</doc>")
@@ -44,10 +44,10 @@ Index: Python-3.11.14/Lib/test/test_sax.py
def test_flush_reparse_deferral_disabled(self):
if not is_expat_2_6_0:
self.skipTest("Linked libexpat doesn't support reparse deferral")
Index: Python-3.11.14/Lib/test/test_xml_etree.py
Index: Python-3.11.15/Lib/test/test_xml_etree.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_xml_etree.py 2025-11-15 19:15:12.861491049 +0100
+++ Python-3.11.14/Lib/test/test_xml_etree.py 2025-11-15 19:15:15.542327817 +0100
--- Python-3.11.15.orig/Lib/test/test_xml_etree.py 2026-03-06 16:07:07.714503769 +0100
+++ Python-3.11.15/Lib/test/test_xml_etree.py 2026-03-06 18:23:34.309977052 +0100
@@ -1620,6 +1620,7 @@
with self.assertRaises(ValueError):
ET.XMLPullParser(events=('start', 'end', 'bogus'))

View File

@@ -0,0 +1,193 @@
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 | 42 +++++++++-
Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst | 5 +
4 files changed, 91 insertions(+), 14 deletions(-)
Index: Python-3.11.15/Doc/library/base64.rst
===================================================================
--- Python-3.11.15.orig/Doc/library/base64.rst 2026-03-03 01:52:57.000000000 +0100
+++ Python-3.11.15/Doc/library/base64.rst 2026-03-06 19:52:36.492967768 +0100
@@ -74,15 +74,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)
@@ -113,6 +118,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.11.15/Lib/base64.py
===================================================================
--- Python-3.11.15.orig/Lib/base64.py 2026-03-06 16:06:30.195774827 +0100
+++ Python-3.11.15/Lib/base64.py 2026-03-06 19:52:36.493488040 +0100
@@ -71,20 +71,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):
@@ -129,8 +148,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.11.15/Lib/test/test_base64.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_base64.py 2026-03-06 16:06:32.552854037 +0100
+++ Python-3.11.15/Lib/test/test_base64.py 2026-03-06 19:52:36.494050069 +0100
@@ -228,6 +228,25 @@
b'\xd3V\xbeo\xf7\x1d')
self.check_decode_type_errors(base64.urlsafe_b64decode)
+ 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')
@@ -259,10 +278,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\xBE\xFF\xFF\xFF'
- self.assertEqual(base64.b64decode(b'++[[//]]', 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.11.15/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.11.15/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst 2026-03-06 19:52:36.494404708 +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.

View File

@@ -0,0 +1,38 @@
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 +++-
Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
Index: Python-3.11.15/Lib/imaplib.py
===================================================================
--- Python-3.11.15.orig/Lib/imaplib.py 2026-03-06 16:06:31.545110864 +0100
+++ Python-3.11.15/Lib/imaplib.py 2026-03-06 19:51:51.838695961 +0100
@@ -132,7 +132,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:
@@ -994,6 +994,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.11.15/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.11.15/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst 2026-03-06 19:51:51.839096617 +0100
@@ -0,0 +1 @@
+Reject control characters in IMAP commands.

View 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.11.15/Lib/poplib.py
===================================================================
--- Python-3.11.15.orig/Lib/poplib.py 2026-03-06 16:06:32.025693538 +0100
+++ Python-3.11.15/Lib/poplib.py 2026-03-06 19:52:31.051258464 +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.11.15/Lib/test/test_poplib.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_poplib.py 2026-03-06 16:06:33.708669394 +0100
+++ Python-3.11.15/Lib/test/test_poplib.py 2026-03-06 19:52:31.052258474 +0100
@@ -16,6 +16,7 @@
from test.support import socket_helper
from test.support import threading_helper
from test.support import warnings_helper
+from test.support import control_characters_c0
asynchat = warnings_helper.import_deprecated('asynchat')
@@ -367,6 +368,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.11.15/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.11.15/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst 2026-03-06 19:52:31.053950556 +0100
@@ -0,0 +1 @@
+Reject control characters in POP3 commands.

View File

@@ -1,359 +0,0 @@
From e717839989908ecea9c1c8f3bd17ec9fb1ac8963 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <storchaka@gmail.com>
Date: Fri, 31 Oct 2025 15:49:51 +0200
Subject: [PATCH] [3.11] gh-136065: Fix quadratic complexity in
os.path.expandvars() (GH-134952) (cherry picked from commit
f029e8db626ddc6e3a3beea4eff511a71aaceb5c)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
---
Lib/ntpath.py | 126 +++-------
Lib/posixpath.py | 43 +--
Lib/test/test_genericpath.py | 14 +
Lib/test/test_ntpath.py | 22 +
Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst | 1
5 files changed, 94 insertions(+), 112 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst
Index: Python-3.11.14/Lib/ntpath.py
===================================================================
--- Python-3.11.14.orig/Lib/ntpath.py 2025-11-15 19:14:27.424009612 +0100
+++ Python-3.11.14/Lib/ntpath.py 2025-11-15 19:14:41.389069009 +0100
@@ -378,17 +378,23 @@
# XXX With COMMAND.COM you can use any characters in a variable name,
# XXX except '^|<>='.
+_varpattern = r"'[^']*'?|%(%|[^%]*%?)|\$(\$|[-\w]+|\{[^}]*\}?)"
+_varsub = None
+_varsubb = None
+
def expandvars(path):
"""Expand shell variables of the forms $var, ${var} and %var%.
Unknown variables are left unchanged."""
path = os.fspath(path)
+ global _varsub, _varsubb
if isinstance(path, bytes):
if b'$' not in path and b'%' not in path:
return path
- import string
- varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii')
- quote = b'\''
+ if not _varsubb:
+ import re
+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
+ sub = _varsubb
percent = b'%'
brace = b'{'
rbrace = b'}'
@@ -397,94 +403,44 @@
else:
if '$' not in path and '%' not in path:
return path
- import string
- varchars = string.ascii_letters + string.digits + '_-'
- quote = '\''
+ if not _varsub:
+ import re
+ _varsub = re.compile(_varpattern, re.ASCII).sub
+ sub = _varsub
percent = '%'
brace = '{'
rbrace = '}'
dollar = '$'
environ = os.environ
- res = path[:0]
- index = 0
- pathlen = len(path)
- while index < pathlen:
- c = path[index:index+1]
- if c == quote: # no expansion within single quotes
- path = path[index + 1:]
- pathlen = len(path)
- try:
- index = path.index(c)
- res += c + path[:index + 1]
- except ValueError:
- res += c + path
- index = pathlen - 1
- elif c == percent: # variable or '%'
- if path[index + 1:index + 2] == percent:
- res += c
- index += 1
- else:
- path = path[index+1:]
- pathlen = len(path)
- try:
- index = path.index(percent)
- except ValueError:
- res += percent + path
- index = pathlen - 1
- else:
- var = path[:index]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = percent + var + percent
- res += value
- elif c == dollar: # variable or '$$'
- if path[index + 1:index + 2] == dollar:
- res += c
- index += 1
- elif path[index + 1:index + 2] == brace:
- path = path[index+2:]
- pathlen = len(path)
- try:
- index = path.index(rbrace)
- except ValueError:
- res += dollar + brace + path
- index = pathlen - 1
- else:
- var = path[:index]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = dollar + brace + var + rbrace
- res += value
- else:
- var = path[:0]
- index += 1
- c = path[index:index + 1]
- while c and c in varchars:
- var += c
- index += 1
- c = path[index:index + 1]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = dollar + var
- res += value
- if c:
- index -= 1
+
+ def repl(m):
+ lastindex = m.lastindex
+ if lastindex is None:
+ return m[0]
+ name = m[lastindex]
+ if lastindex == 1:
+ if name == percent:
+ return name
+ if not name.endswith(percent):
+ return m[0]
+ name = name[:-1]
else:
- res += c
- index += 1
- return res
+ if name == dollar:
+ return name
+ if name.startswith(brace):
+ if not name.endswith(rbrace):
+ return m[0]
+ name = name[1:-1]
+
+ try:
+ if environ is None:
+ return os.fsencode(os.environ[os.fsdecode(name)])
+ else:
+ return environ[name]
+ except KeyError:
+ return m[0]
+
+ return sub(repl, path)
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
Index: Python-3.11.14/Lib/posixpath.py
===================================================================
--- Python-3.11.14.orig/Lib/posixpath.py 2025-11-15 19:14:27.465471369 +0100
+++ Python-3.11.14/Lib/posixpath.py 2025-11-15 19:14:41.389334199 +0100
@@ -287,42 +287,41 @@
# This expands the forms $variable and ${variable} only.
# Non-existent variables are left unchanged.
-_varprog = None
-_varprogb = None
+_varpattern = r'\$(\w+|\{[^}]*\}?)'
+_varsub = None
+_varsubb = None
def expandvars(path):
"""Expand shell variables of form $var and ${var}. Unknown variables
are left unchanged."""
path = os.fspath(path)
- global _varprog, _varprogb
+ global _varsub, _varsubb
if isinstance(path, bytes):
if b'$' not in path:
return path
- if not _varprogb:
+ if not _varsubb:
import re
- _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII)
- search = _varprogb.search
+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
+ sub = _varsubb
start = b'{'
end = b'}'
environ = getattr(os, 'environb', None)
else:
if '$' not in path:
return path
- if not _varprog:
+ if not _varsub:
import re
- _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII)
- search = _varprog.search
+ _varsub = re.compile(_varpattern, re.ASCII).sub
+ sub = _varsub
start = '{'
end = '}'
environ = os.environ
- i = 0
- while True:
- m = search(path, i)
- if not m:
- break
- i, j = m.span(0)
- name = m.group(1)
- if name.startswith(start) and name.endswith(end):
+
+ def repl(m):
+ name = m[1]
+ if name.startswith(start):
+ if not name.endswith(end):
+ return m[0]
name = name[1:-1]
try:
if environ is None:
@@ -330,13 +329,11 @@
else:
value = environ[name]
except KeyError:
- i = j
+ return m[0]
else:
- tail = path[j:]
- path = path[:i] + value
- i = len(path)
- path += tail
- return path
+ return value
+
+ return sub(repl, path)
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
Index: Python-3.11.14/Lib/test/test_genericpath.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_genericpath.py 2025-11-15 19:14:28.470950071 +0100
+++ Python-3.11.14/Lib/test/test_genericpath.py 2025-11-15 19:14:41.389533528 +0100
@@ -7,6 +7,7 @@
import sys
import unittest
import warnings
+from test import support
from test.support import is_emscripten
from test.support import os_helper
from test.support import warnings_helper
@@ -434,6 +435,19 @@
os.fsencode('$bar%s bar' % nonascii))
check(b'$spam}bar', os.fsencode('%s}bar' % nonascii))
+ @support.requires_resource('cpu')
+ def test_expandvars_large(self):
+ expandvars = self.pathmodule.expandvars
+ with os_helper.EnvironmentVarGuard() as env:
+ env.clear()
+ env["A"] = "B"
+ n = 100_000
+ self.assertEqual(expandvars('$A'*n), 'B'*n)
+ self.assertEqual(expandvars('${A}'*n), 'B'*n)
+ self.assertEqual(expandvars('$A!'*n), 'B!'*n)
+ self.assertEqual(expandvars('${A}A'*n), 'BA'*n)
+ self.assertEqual(expandvars('${'*10*n), '${'*10*n)
+
def test_abspath(self):
self.assertIn("foo", self.pathmodule.abspath("foo"))
with warnings.catch_warnings():
Index: Python-3.11.14/Lib/test/test_ntpath.py
===================================================================
--- Python-3.11.14.orig/Lib/test/test_ntpath.py 2025-11-15 19:14:29.042372971 +0100
+++ Python-3.11.14/Lib/test/test_ntpath.py 2025-11-15 19:14:41.389799697 +0100
@@ -6,8 +6,8 @@
import unittest
import warnings
from ntpath import ALLOW_MISSING
-from test.support import os_helper
-from test.support import TestFailed, is_emscripten
+from test import support
+from test.support import os_helper, is_emscripten
from test.support.os_helper import FakePath
from test import test_genericpath
from tempfile import TemporaryFile
@@ -57,7 +57,7 @@
fn = fn.replace("\\", "\\\\")
gotResult = eval(fn)
if wantResult != gotResult and _norm(wantResult) != _norm(gotResult):
- raise TestFailed("%s should return: %s but returned: %s" \
+ raise support.TestFailed("%s should return: %s but returned: %s" \
%(str(fn), str(wantResult), str(gotResult)))
# then with bytes
@@ -73,7 +73,7 @@
warnings.simplefilter("ignore", DeprecationWarning)
gotResult = eval(fn)
if _norm(wantResult) != _norm(gotResult):
- raise TestFailed("%s should return: %s but returned: %s" \
+ raise support.TestFailed("%s should return: %s but returned: %s" \
%(str(fn), str(wantResult), repr(gotResult)))
@@ -820,6 +820,19 @@
check('%spam%bar', '%sbar' % nonascii)
check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii)
+ @support.requires_resource('cpu')
+ def test_expandvars_large(self):
+ expandvars = ntpath.expandvars
+ with os_helper.EnvironmentVarGuard() as env:
+ env.clear()
+ env["A"] = "B"
+ n = 100_000
+ self.assertEqual(expandvars('%A%'*n), 'B'*n)
+ self.assertEqual(expandvars('%A%A'*n), 'BA'*n)
+ self.assertEqual(expandvars("''"*n + '%%'), "''"*n + '%')
+ self.assertEqual(expandvars("%%"*n), "%"*n)
+ self.assertEqual(expandvars("$$"*n), "$"*n)
+
def test_expanduser(self):
tester('ntpath.expanduser("test")', 'test')
@@ -1090,6 +1103,7 @@
self.assertIsInstance(b_final_path, bytes)
self.assertGreater(len(b_final_path), 0)
+
class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase):
pathmodule = ntpath
attributes = ['relpath']
Index: Python-3.11.14/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ Python-3.11.14/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst 2025-11-15 19:14:41.390091148 +0100
@@ -0,0 +1 @@
+Fix quadratic complexity in :func:`os.path.expandvars`.

Binary file not shown.

File diff suppressed because one or more lines are too long

BIN
Python-3.11.15.tar.xz LFS Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -12,9 +12,11 @@ for the definition of this variable.
Doc/library/functions.rst | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -316,7 +316,8 @@ html_context = {
Index: Python-3.11.15/Doc/conf.py
===================================================================
--- Python-3.11.15.orig/Doc/conf.py 2026-03-03 01:52:57.000000000 +0100
+++ Python-3.11.15/Doc/conf.py 2026-03-06 18:23:39.828089970 +0100
@@ -316,7 +316,8 @@
}
# This 'Last updated on:' timestamp is inserted at the bottom of every page.
@@ -24,9 +26,11 @@ for the definition of this variable.
# Path to find HTML templates.
templates_path = ['tools/templates']
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1356,7 +1356,7 @@ are always available. They are listed h
Index: Python-3.11.15/Doc/library/functions.rst
===================================================================
--- Python-3.11.15.orig/Doc/library/functions.rst 2026-03-03 01:52:57.000000000 +0100
+++ Python-3.11.15/Doc/library/functions.rst 2026-03-06 18:23:39.829089979 +0100
@@ -1356,7 +1356,7 @@
(where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`,
and :mod:`shutil`.

View File

@@ -3,10 +3,10 @@
Misc/NEWS | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
Index: Python-3.11.14/Doc/using/configure.rst
Index: Python-3.11.15/Doc/using/configure.rst
===================================================================
--- Python-3.11.14.orig/Doc/using/configure.rst 2025-11-15 19:14:54.096952433 +0100
+++ Python-3.11.14/Doc/using/configure.rst 2025-11-15 19:15:04.439920979 +0100
--- Python-3.11.15.orig/Doc/using/configure.rst 2026-03-06 16:06:43.304945441 +0100
+++ Python-3.11.15/Doc/using/configure.rst 2026-03-06 16:06:55.576758292 +0100
@@ -43,7 +43,6 @@
See :data:`sys.int_info.bits_per_digit <sys.int_info>`.
@@ -29,11 +29,11 @@ Index: Python-3.11.14/Doc/using/configure.rst
.. option:: --enable-framework=INSTALLDIR
Create a Python.framework rather than a traditional Unix install. Optional
Index: Python-3.11.14/Misc/NEWS
Index: Python-3.11.15/Misc/NEWS
===================================================================
--- Python-3.11.14.orig/Misc/NEWS 2025-11-15 19:14:54.096952433 +0100
+++ Python-3.11.14/Misc/NEWS 2025-11-15 19:15:04.445942414 +0100
@@ -9987,7 +9987,7 @@
--- Python-3.11.15.orig/Misc/NEWS 2026-03-06 16:06:43.304945441 +0100
+++ Python-3.11.15/Misc/NEWS 2026-03-06 16:06:55.580059032 +0100
@@ -10081,7 +10081,7 @@
- bpo-40939: Removed documentation for the removed ``PyParser_*`` C API.
- bpo-43795: The list in :ref:`limited-api-list` now shows the public name

View File

@@ -1,3 +1,133 @@
-------------------------------------------------------------------
Fri Mar 6 18:54:51 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
- Update to 3.11.15:
- Security
- gh-144125: BytesGenerator will now refuse to serialize
(write) headers that are unsafely folded or delimited; see
verify_generated_headers. (Contributed by Bas Bloemsaat and
Petr Viktorin in gh-121650).
- gh-143935: Fixed a bug in the folding of comments when
flattening an email message using a modern email policy.
Comments consisting of a very long sequence of non-foldable
characters could trigger a forced line wrap that omitted
the required leading space on the continuation line,
causing the remainder of the comment to be interpreted as
a new header field. This enabled header injection with
carefully crafted inputs (bsc#1257029 CVE-2025-11468).
- gh-143925: Reject control characters in data: URL media
types (bsc#1257046, CVE-2025-15282).
- gh-143919: Reject control characters in http.cookies.Morsel
fields and values (bsc#1257031, CVE-2026-0672).
- gh-143916: Reject C0 control characters within
wsgiref.headers.Headers fields, values, and parameters
(bsc#1257042, CVE-2026-0865).
- gh-142145: Remove quadratic behavior in xml.minidom node ID
cache clearing. In order to do this without breaking
existing users, we also add the ownerDocument attribute to
xml.dom.minidom elements and attributes created by directly
instantiating the Element or Attr class. Note that this way
of creating nodes is not supported; creator functions like
xml.dom.Document.documentElement() should be used instead
(bsc#1254997, CVE-2025-12084).
- gh-137836: Add support of the “plaintext” element, RAWTEXT
elements “xmp”, “iframe”, “noembed” and “noframes”, and
optionally RAWTEXT element “noscript” in
html.parser.HTMLParser.
- gh-136063: email.message: ensure linear complexity for
legacy HTTP parameters parsing. Patch by Bénédikt Tran.
- gh-136065: Fix quadratic complexity in
os.path.expandvars() (bsc#1252974, CVE-2025-6075).
- gh-119451: Fix a potential memory denial of service in the
http.client module. When connecting to a malicious server,
it could cause an arbitrary amount of memory to be
allocated. This could have led to symptoms including
a MemoryError, swapping, out of memory (OOM) killed
processes or containers, or even system crashes
(CVE-2025-13836, bsc#1254400).
- gh-119452: Fix a potential memory denial of service in the
http.server module. When a malicious user is connected to
the CGI server on Windows, it could cause an arbitrary
amount of memory to be allocated. This could have led to
symptoms including a MemoryError, swapping, out of memory
(OOM) killed processes or containers, or even system
crashes.
- gh-119342: Fix a potential memory denial of service in the
plistlib module. When reading a Plist file received from
untrusted source, it could cause an arbitrary amount of
memory to be allocated. This could have led to symptoms
including a MemoryError, swapping, out of memory (OOM)
killed processes or containers, or even system crashes
(bsc#1254401, CVE-2025-13837).
- Library
- gh-144833: Fixed a use-after-free in ssl when SSL_new()
returns NULL in newPySSLSocket(). The error was reported
via a dangling pointer after the object had already been
freed.
- gh-144363: Update bundled libexpat to 2.7.4
- gh-90949: Add SetAllocTrackerActivationThreshold() and
SetAllocTrackerMaximumAmplification() to xmlparser objects
to prevent use of disproportional amounts of dynamic memory
from within an Expat parser. Patch by Bénédikt Tran.
- Core and Builtins
- gh-120384: Fix an array out of bounds crash in
list_ass_subscript, which could be invoked via some
specificly tailored input: including concurrent
modification of a list object, where one thread assigns
a slice and another clears it.
- gh-120298: Fix use-after free in list_richcompare_impl
which can be invoked via some specificly tailored evil
input.
Remove upstreamed patches:
- CVE-2025-11468-email-hdr-fold-comment.patch
- CVE-2025-12084-minidom-quad-search.patch
- CVE-2025-13836-http-resp-cont-len.patch
- CVE-2025-13837-plistlib-mailicious-length.patch
- CVE-2025-6075-expandvars-perf-degrad.patch
- CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
- CVE-2026-0865-wsgiref-ctrl-chars.patch
- CVE-2025-15282-urllib-ctrl-chars.patch
-------------------------------------------------------------------
Wed Feb 11 19:09:06 CET 2026 - Matej Cepl <mcepl@suse.com>
- CVE-2025-11468: preserving parens when folding comments in
email headers (bsc#1257029, gh#python/cpython#143935).
CVE-2025-11468-email-hdr-fold-comment.patch
- CVE-2026-0672: rejects control characters in http cookies.
(bsc#1257031, gh#python/cpython#143919)
CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
- CVE-2026-0865: rejecting control characters in
wsgiref.headers.Headers, which could be abused for injecting
false HTTP headers. (bsc#1257042, gh#python/cpython#143916)
CVE-2026-0865-wsgiref-ctrl-chars.patch
- CVE-2025-15366: basically the same as the previous patch for
IMAP protocol. (bsc#1257044, gh#python/cpython#143921)
CVE-2025-15366-imap-ctrl-chars.patch
- CVE-2025-15282: basically the same as the previous patch for
urllib library. (bsc#1257046, gh#python/cpython#143925)
CVE-2025-15282-urllib-ctrl-chars.patch
- CVE-2025-15367: basically the same as the previous patch for
poplib library. (bsc#1257041, gh#python/cpython#143923)
CVE-2025-15367-poplib-ctrl-chars.patch
- CVE-2025-12781: fix decoding with non-standard Base64 alphabet
(bsc#1257108, gh#python/cpython#125346)
CVE-2025-12781-b64decode-alt-chars.patch
-------------------------------------------------------------------
Thu Dec 18 10:33:44 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2025-13836-http-resp-cont-len.patch (bsc#1254400,
CVE-2025-13836) to prevent reading an HTTP response from
a server, if no read amount is specified, with using
Content-Length per default as the length.
- Add CVE-2025-12084-minidom-quad-search.patch prevent quadratic
behavior in node ID cache clearing (CVE-2025-12084,
bsc#1254997).
- Add CVE-2025-13837-plistlib-mailicious-length.patch protect
against OOM when loading malicious content (CVE-2025-13837,
bsc#1254401).
-------------------------------------------------------------------
Thu Nov 13 17:13:03 UTC 2025 - Matej Cepl <mcepl@cepl.eu>

View File

@@ -107,7 +107,7 @@
# _md5.cpython-38m-x86_64-linux-gnu.so
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
Name: %{python_pkg_name}%{psuffix}
Version: 3.11.14
Version: 3.11.15
Release: 0
Summary: Python 3 Interpreter
License: Python-2.0
@@ -188,9 +188,16 @@ Patch22: gh120226-fix-sendfile-test-kernel-610.patch
Patch24: add-loongarch64-support.patch
# PATCH-FIX-OPENSUSE gh139257-Support-docutils-0.22.patch gh#python/cpython#139257 daniel.garcia@suse.com
Patch25: gh139257-Support-docutils-0.22.patch
# PATCH-FIX-UPSTREAM CVE-2025-6075-expandvars-perf-degrad.patch bsc#1252974 mcepl@suse.com
# Avoid potential quadratic complexity vulnerabilities in path modules
Patch26: CVE-2025-6075-expandvars-perf-degrad.patch
# PATCH-FIX-UPSTREAM CVE-2025-15366-imap-ctrl-chars.patch bsc#1257044 mcepl@suse.com
# Reject control characters in wsgiref.headers.Headers
Patch33: CVE-2025-15366-imap-ctrl-chars.patch
# PATCH-FIX-UPSTREAM CVE-2025-15367-poplib-ctrl-chars.patch bsc#1257041 mcepl@suse.com
# Reject control characters in poplib
Patch35: CVE-2025-15367-poplib-ctrl-chars.patch
# PATCH-FIX-UPSTREAM CVE-2025-12781-b64decode-alt-chars.patch bsc#1257108 mcepl@suse.com
# Fix decoding with non-standard Base64 alphabet gh#python/cpython#125346
Patch36: CVE-2025-12781-b64decode-alt-chars.patch
### END OF PATCHES
BuildRequires: autoconf-archive
BuildRequires: automake
BuildRequires: crypto-policies-scripts
@@ -546,6 +553,9 @@ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH \
%check
export SUSE_VERSION="0%{?suse_version}"
export SLE_VERSION="0%{?sle_version}"
echo "Show the openssl version"
openssl version -a
echo ""
%if %{with general}
# exclude test_gdb -- it doesn't run in buildservice anyway, and fails on missing debuginfos
# when you install gdb into your test env