Compare commits

...

No commits in common. "devel" and "devel" have entirely different histories.
devel ... devel

10 changed files with 97 additions and 1089 deletions

View File

@ -10,11 +10,9 @@ Subject: [PATCH 1/2] fix(doc-tools): use sphinx.locale._ as gettext() for
Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst | 1 +
2 files changed, 5 insertions(+), 4 deletions(-)
Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
===================================================================
--- Python-3.9.22.orig/Doc/tools/extensions/pyspecific.py 2025-04-11 09:49:58.417019238 +0200
+++ Python-3.9.22/Doc/tools/extensions/pyspecific.py 2025-04-11 09:50:56.818993764 +0200
@@ -27,7 +27,7 @@
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -26,7 +26,7 @@ try:
from sphinx.errors import NoUri
except ImportError:
from sphinx.environment import NoUri
@ -23,7 +21,7 @@ Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
from sphinx.util import status_iterator, logging
from sphinx.util.nodes import split_explicit_title
from sphinx.writers.text import TextWriter, TextTranslator
@@ -111,7 +111,7 @@
@@ -110,7 +110,7 @@ class ImplementationDetail(Directive):
def run(self):
pnode = nodes.compound(classes=['impl-detail'])
@ -32,7 +30,7 @@ Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
content = self.content
add_text = nodes.strong(label, label)
if self.arguments:
@@ -180,7 +180,7 @@
@@ -179,7 +179,7 @@ class AuditEvent(Directive):
else:
args = []
@ -41,18 +39,16 @@ Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
text = label.format(name="``{}``".format(name),
args=", ".join("``{}``".format(a) for a in args if a))
@@ -380,7 +380,7 @@
@@ -358,7 +358,7 @@ class DeprecatedRemoved(Directive):
else:
label = self._removed_label
- label = translators['sphinx'].gettext(label)
+ label = sphinx_gettext(label)
text = label.format(deprecated=version[0], removed=version[1])
text = label.format(deprecated=self.arguments[0], removed=self.arguments[1])
if len(self.arguments) == 3:
inodes, messages = self.state.inline_text(self.arguments[2],
Index: Python-3.9.22/Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ Python-3.9.22/Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst 2025-04-11 09:50:08.952333342 +0200
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst
@@ -0,0 +1 @@
+Use sphinx.locale._ as the gettext function in pyspecific.py.

View File

@ -1,97 +0,0 @@
From 37bc08c699f48461be5e000b2da9212237a1ca0f Mon Sep 17 00:00:00 2001
From: JohnJamesUtley <jjutley231@gmail.com>
Date: Tue, 25 Apr 2023 16:01:03 -0400
Subject: [PATCH 1/4] Adds checks to ensure that bracketed hosts found by
urlsplit are of IPv6 or IPvFuture format
---
Lib/test/test_urlparse.py | 26 ++++++++++
Lib/urllib/parse.py | 16 +++++-
Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst | 2
3 files changed, 43 insertions(+), 1 deletion(-)
create mode 100644 Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -1135,6 +1135,32 @@ class UrlParseTestCase(unittest.TestCase
self.assertEqual(p2.scheme, 'tel')
self.assertEqual(p2.path, '+31641044153')
+ def test_invalid_bracketed_hosts(self):
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
+
+ def test_splitting_bracketed_hosts(self):
+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')
+ self.assertEqual(p1.hostname, 'v6a.ip')
+ self.assertEqual(p1.username, 'user')
+ self.assertEqual(p1.path, '/path')
+ p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query')
+ self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test')
+ self.assertEqual(p2.username, 'user')
+ self.assertEqual(p2.path, '/path')
+ p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query')
+ self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test')
+ self.assertEqual(p3.username, 'user')
+ self.assertEqual(p3.path, '/path')
+
def test_port_casting_failure_message(self):
message = "Port could not be cast to integer value as 'oracle'"
p1 = urllib.parse.urlparse('http://Server=sde; Service=sde:oracle')
--- a/Lib/urllib/parse.py
+++ b/Lib/urllib/parse.py
@@ -36,6 +36,7 @@ import sys
import types
import collections
import warnings
+import ipaddress
__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
"urlsplit", "urlunsplit", "urlencode", "parse_qs",
@@ -442,6 +443,17 @@ def _checknetloc(netloc):
raise ValueError("netloc '" + netloc + "' contains invalid " +
"characters under NFKC normalization")
+# Valid bracketed hosts are defined in
+# https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/
+def _check_bracketed_host(hostname):
+ if hostname.startswith('v'):
+ if not re.match(r"\Av[a-fA-F0-9]+\..+\Z", hostname):
+ raise ValueError(f"IPvFuture address is invalid")
+ else:
+ ip = ipaddress.ip_address(hostname) # Throws Value Error if not IPv6 or IPv4
+ if isinstance(ip, ipaddress.IPv4Address):
+ raise ValueError(f"An IPv4 address cannot be in brackets")
+
def urlsplit(url, scheme='', allow_fragments=True):
"""Parse a URL into 5 components:
<scheme>://<netloc>/<path>?<query>#<fragment>
@@ -488,12 +500,14 @@ def urlsplit(url, scheme='', allow_fragm
break
else:
scheme, url = url[:i].lower(), url[i+1:]
-
if url[:2] == '//':
netloc, url = _splitnetloc(url, 2)
if (('[' in netloc and ']' not in netloc) or
(']' in netloc and '[' not in netloc)):
raise ValueError("Invalid IPv6 URL")
+ if '[' in netloc and ']' in netloc:
+ bracketed_host = netloc.partition('[')[2].partition(']')[0]
+ _check_bracketed_host(bracketed_host)
if allow_fragments and '#' in url:
url, fragment = url.split('#', 1)
if '?' in url:
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
@@ -0,0 +1,2 @@
+Add checks to ensure that ``[`` bracketed ``]`` hosts found by
+:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format.

View File

@ -1,282 +0,0 @@
From ae0d64cb185900712c40a65d7d8aa118f9903d57 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@python.org>
Date: Fri, 1 Nov 2024 14:11:47 +0100
Subject: [PATCH] [3.11] gh-124651: Quote template strings in `venv` activation
scripts (GH-124712) (GH-126185) (#126269)
(cherry picked from commit ae961ae94bf19c8f8c7fbea3d1c25cc55ce8ae97)
---
Lib/test/test_venv.py | 81 ++++++++++
Lib/venv/__init__.py | 42 ++++-
Lib/venv/scripts/common/activate | 6
Lib/venv/scripts/nt/activate.bat | 4
Lib/venv/scripts/posix/activate.csh | 6
Lib/venv/scripts/posix/activate.fish | 6
Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst | 1
7 files changed, 130 insertions(+), 16 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -14,6 +14,7 @@ import struct
import subprocess
import sys
import tempfile
+import shlex
from test.support import (captured_stdout, captured_stderr, requires_zlib,
can_symlink, EnvironmentVarGuard, rmtree,
import_module,
@@ -85,6 +86,10 @@ class BaseTest(unittest.TestCase):
result = f.read()
return result
+ def assertEndsWith(self, string, tail):
+ if not string.endswith(tail):
+ self.fail(f"String {string!r} does not end with {tail!r}")
+
class BasicTest(BaseTest):
"""Test venv module functionality."""
@@ -342,6 +347,82 @@ class BasicTest(BaseTest):
'import sys; print(sys.executable)'])
self.assertEqual(out.strip(), envpy.encode())
+ # gh-124651: test quoted strings
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+ def test_special_chars_bash(self):
+ """
+ Test that the template strings are quoted properly (bash)
+ """
+ rmtree(self.env_dir)
+ bash = shutil.which('bash')
+ if bash is None:
+ self.skipTest('bash required for this test')
+ env_name = '"\';&&$e|\'"'
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate')
+ test_script = os.path.join(self.env_dir, 'test_special_chars.sh')
+ with open(test_script, "w") as f:
+ f.write(f'source {shlex.quote(activate)}\n'
+ 'python -c \'import sys; print(sys.executable)\'\n'
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
+ 'deactivate\n')
+ out, err = check_output([bash, test_script])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
+ # gh-124651: test quoted strings
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+ def test_special_chars_csh(self):
+ """
+ Test that the template strings are quoted properly (csh)
+ """
+ rmtree(self.env_dir)
+ csh = shutil.which('tcsh') or shutil.which('csh')
+ if csh is None:
+ self.skipTest('csh required for this test')
+ env_name = '"\';&&$e|\'"'
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate.csh')
+ test_script = os.path.join(self.env_dir, 'test_special_chars.csh')
+ with open(test_script, "w") as f:
+ f.write(f'source {shlex.quote(activate)}\n'
+ 'python -c \'import sys; print(sys.executable)\'\n'
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
+ 'deactivate\n')
+ out, err = check_output([csh, test_script])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
+ # gh-124651: test quoted strings on Windows
+ @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
+ def test_special_chars_windows(self):
+ """
+ Test that the template strings are quoted properly on Windows
+ """
+ rmtree(self.env_dir)
+ env_name = "'&&^$e"
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate.bat')
+ test_batch = os.path.join(self.env_dir, 'test_special_chars.bat')
+ with open(test_batch, "w") as f:
+ f.write('@echo off\n'
+ f'"{activate}" & '
+ f'{self.exe} -c "import sys; print(sys.executable)" & '
+ f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & '
+ 'deactivate')
+ out, err = check_output([test_batch])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
@unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
def test_unicode_in_batch_file(self):
"""
--- a/Lib/venv/__init__.py
+++ b/Lib/venv/__init__.py
@@ -11,6 +11,7 @@ import subprocess
import sys
import sysconfig
import types
+import shlex
CORE_VENV_DEPS = ('pip', 'setuptools')
@@ -348,11 +349,41 @@ class EnvBuilder:
:param context: The information for the environment creation request
being processed.
"""
- text = text.replace('__VENV_DIR__', context.env_dir)
- text = text.replace('__VENV_NAME__', context.env_name)
- text = text.replace('__VENV_PROMPT__', context.prompt)
- text = text.replace('__VENV_BIN_NAME__', context.bin_name)
- text = text.replace('__VENV_PYTHON__', context.env_exe)
+ replacements = {
+ '__VENV_DIR__': context.env_dir,
+ '__VENV_NAME__': context.env_name,
+ '__VENV_PROMPT__': context.prompt,
+ '__VENV_BIN_NAME__': context.bin_name,
+ '__VENV_PYTHON__': context.env_exe,
+ }
+
+ def quote_ps1(s):
+ """
+ This should satisfy PowerShell quoting rules [1], unless the quoted
+ string is passed directly to Windows native commands [2].
+ [1]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules
+ [2]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#passing-arguments-that-contain-quote-characters
+ """
+ s = s.replace("'", "''")
+ return f"'{s}'"
+
+ def quote_bat(s):
+ return s
+
+ # gh-124651: need to quote the template strings properly
+ quote = shlex.quote
+ script_path = context.script_path
+ if script_path.endswith('.ps1'):
+ quote = quote_ps1
+ elif script_path.endswith('.bat'):
+ quote = quote_bat
+ else:
+ # fallbacks to POSIX shell compliant quote
+ quote = shlex.quote
+
+ replacements = {key: quote(s) for key, s in replacements.items()}
+ for key, quoted in replacements.items():
+ text = text.replace(key, quoted)
return text
def install_scripts(self, context, path):
@@ -392,6 +423,7 @@ class EnvBuilder:
with open(srcfile, 'rb') as f:
data = f.read()
if not srcfile.endswith(('.exe', '.pdb')):
+ context.script_path = srcfile
try:
data = data.decode('utf-8')
data = self.replace_variables(data, context)
--- a/Lib/venv/scripts/common/activate
+++ b/Lib/venv/scripts/common/activate
@@ -37,11 +37,11 @@ deactivate () {
# unset irrelevant variables
deactivate nondestructive
-VIRTUAL_ENV="__VENV_DIR__"
+VIRTUAL_ENV=__VENV_DIR__
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
-PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+PATH="$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
export PATH
# unset PYTHONHOME if set
@@ -54,7 +54,7 @@ fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
- PS1="__VENV_PROMPT__${PS1:-}"
+ PS1=__VENV_PROMPT__"${PS1:-}"
export PS1
fi
--- a/Lib/venv/scripts/nt/activate.bat
+++ b/Lib/venv/scripts/nt/activate.bat
@@ -8,7 +8,7 @@ if defined _OLD_CODEPAGE (
"%SystemRoot%\System32\chcp.com" 65001 > nul
)
-set VIRTUAL_ENV=__VENV_DIR__
+set "VIRTUAL_ENV=__VENV_DIR__"
if not defined PROMPT set PROMPT=$P$G
@@ -24,7 +24,7 @@ set PYTHONHOME=
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
-set PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%
+set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"
:END
if defined _OLD_CODEPAGE (
--- a/Lib/venv/scripts/posix/activate.csh
+++ b/Lib/venv/scripts/posix/activate.csh
@@ -8,16 +8,16 @@ alias deactivate 'test $?_OLD_VIRTUAL_PA
# Unset irrelevant variables.
deactivate nondestructive
-setenv VIRTUAL_ENV "__VENV_DIR__"
+setenv VIRTUAL_ENV __VENV_DIR__
set _OLD_VIRTUAL_PATH="$PATH"
-setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+setenv PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
- set prompt = "__VENV_PROMPT__$prompt"
+ set prompt = __VENV_PROMPT__"$prompt"
endif
alias pydoc python -m pydoc
--- a/Lib/venv/scripts/posix/activate.fish
+++ b/Lib/venv/scripts/posix/activate.fish
@@ -29,10 +29,10 @@ end
# Unset irrelevant variables.
deactivate nondestructive
-set -gx VIRTUAL_ENV "__VENV_DIR__"
+set -gx VIRTUAL_ENV __VENV_DIR__
set -gx _OLD_VIRTUAL_PATH $PATH
-set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH
+set -gx PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__ $PATH
# Unset PYTHONHOME if set.
if set -q PYTHONHOME
@@ -52,7 +52,7 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
set -l old_status $status
# Output the venv prompt; color taken from the blue of the Python logo.
- printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal)
+ printf "%s%s%s" (set_color 4B8BBE) __VENV_PROMPT__ (set_color normal)
# Restore the return status of the previous command.
echo "exit $old_status" | .
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
@@ -0,0 +1 @@
+Properly quote template strings in :mod:`venv` activation scripts.

View File

@ -1,426 +0,0 @@
From 0d5d68f7075788b6912f8632dc841dca97ece409 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <storchaka@gmail.com>
Date: Tue, 20 May 2025 15:46:57 +0300
Subject: [PATCH] [3.9] gh-133767: Fix use-after-free in the unicode-escape
decoder with an error handler (GH-129648) (GH-133944)
If the error handler is used, a new bytes object is created to set as
the object attribute of UnicodeDecodeError, and that bytes object then
replaces the original data. A pointer to the decoded data will became invalid
after destroying that temporary bytes object. So we need other way to return
the first invalid escape from _PyUnicode_DecodeUnicodeEscapeInternal().
_PyBytes_DecodeEscape() does not have such issue, because it does not
use the error handlers registry, but it should be changed for compatibility
with _PyUnicode_DecodeUnicodeEscapeInternal().
(cherry picked from commit 9f69a58623bd01349a18ba0c7a9cb1dad6a51e8e)
(cherry picked from commit 6279eb8c076d89d3739a6edb393e43c7929b429d)
(cherry picked from commit a75953b347716fff694aa59a7c7c2489fa50d1f5)
(cherry picked from commit 0c33e5baedf18ebcb04bc41dff7cfc614d5ea5fe)
(cherry picked from commit 8b528cacbbde60504f6ac62784d04889d285f18b)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
---
Include/cpython/bytesobject.h | 4
Include/cpython/unicodeobject.h | 13 ++
Lib/test/test_codeccallbacks.py | 37 ++++++++
Lib/test/test_codecs.py | 39 ++++++--
Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst | 2
Objects/bytesobject.c | 40 ++++++--
Objects/unicodeobject.c | 45 +++++++---
Parser/pegen/parse_string.c | 24 +++--
8 files changed, 164 insertions(+), 40 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst
--- a/Include/cpython/bytesobject.h
+++ b/Include/cpython/bytesobject.h
@@ -25,6 +25,10 @@ PyAPI_FUNC(PyObject*) _PyBytes_FromHex(
int use_bytearray);
/* Helper for PyBytes_DecodeEscape that detects invalid escape chars. */
+PyAPI_FUNC(PyObject*) _PyBytes_DecodeEscape2(const char *, Py_ssize_t,
+ const char *,
+ int *, const char **);
+// Export for binary compatibility.
PyAPI_FUNC(PyObject *) _PyBytes_DecodeEscape(const char *, Py_ssize_t,
const char *, const char **);
--- a/Include/cpython/unicodeobject.h
+++ b/Include/cpython/unicodeobject.h
@@ -866,6 +866,19 @@ PyAPI_FUNC(PyObject*) _PyUnicode_DecodeU
);
/* Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape
chars. */
+PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal2(
+ const char *string, /* Unicode-Escape encoded string */
+ Py_ssize_t length, /* size of string */
+ const char *errors, /* error handling */
+ Py_ssize_t *consumed, /* bytes consumed */
+ int *first_invalid_escape_char, /* on return, if not -1, contain the first
+ invalid escaped char (<= 0xff) or invalid
+ octal escape (> 0xff) in string. */
+ const char **first_invalid_escape_ptr); /* on return, if not NULL, may
+ point to the first invalid escaped
+ char in string.
+ May be NULL if errors is not NULL. */
+// Export for binary compatibility.
PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal(
const char *string, /* Unicode-Escape encoded string */
Py_ssize_t length, /* size of string */
--- a/Lib/test/test_codeccallbacks.py
+++ b/Lib/test/test_codeccallbacks.py
@@ -1,6 +1,7 @@
import codecs
import html.entities
import itertools
+import re
import sys
import unicodedata
import unittest
@@ -1124,7 +1125,7 @@ class CodecCallbackTest(unittest.TestCas
text = 'abc<def>ghi'*n
text.translate(charmap)
- def test_mutatingdecodehandler(self):
+ def test_mutating_decode_handler(self):
baddata = [
("ascii", b"\xff"),
("utf-7", b"++"),
@@ -1159,6 +1160,40 @@ class CodecCallbackTest(unittest.TestCas
for (encoding, data) in baddata:
self.assertEqual(data.decode(encoding, "test.mutating"), "\u4242")
+ def test_mutating_decode_handler_unicode_escape(self):
+ decode = codecs.unicode_escape_decode
+ def mutating(exc):
+ if isinstance(exc, UnicodeDecodeError):
+ r = data.get(exc.object[:exc.end])
+ if r is not None:
+ exc.object = r[0] + exc.object[exc.end:]
+ return ('\u0404', r[1])
+ raise AssertionError("don't know how to handle %r" % exc)
+
+ codecs.register_error('test.mutating2', mutating)
+ data = {
+ br'\x0': (b'\\', 0),
+ br'\x3': (b'xxx\\', 3),
+ br'\x5': (b'x\\', 1),
+ }
+ def check(input, expected, msg):
+ with self.assertWarns(DeprecationWarning) as cm:
+ self.assertEqual(decode(input, 'test.mutating2'), (expected, len(input)))
+ self.assertIn(msg, str(cm.warning))
+
+ check(br'\x0n\z', '\u0404\n\\z', r"invalid escape sequence '\z'")
+ check(br'\x0z', '\u0404\\z', r"invalid escape sequence '\z'")
+
+ check(br'\x3n\zr', '\u0404\n\\zr', r"invalid escape sequence '\z'")
+ check(br'\x3zr', '\u0404\\zr', r"invalid escape sequence '\z'")
+ check(br'\x3z5', '\u0404\\z5', r"invalid escape sequence '\z'")
+ check(memoryview(br'\x3z5x')[:-1], '\u0404\\z5', r"invalid escape sequence '\z'")
+ check(memoryview(br'\x3z5xy')[:-2], '\u0404\\z5', r"invalid escape sequence '\z'")
+
+ check(br'\x5n\z', '\u0404\n\\z', r"invalid escape sequence '\z'")
+ check(br'\x5z', '\u0404\\z', r"invalid escape sequence '\z'")
+ check(memoryview(br'\x5zy')[:-1], '\u0404\\z', r"invalid escape sequence '\z'")
+
# issue32583
def test_crashing_decode_handler(self):
# better generating one more character to fill the extra space slot
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -1178,20 +1178,32 @@ class EscapeDecodeTest(unittest.TestCase
check(br"[\501]", b"[A]")
check(br"[\x41]", b"[A]")
check(br"[\x410]", b"[A0]")
+
+ def test_warnings(self):
+ decode = codecs.escape_decode
+ check = coding_checker(self, decode)
for i in range(97, 123):
b = bytes([i])
if b not in b'abfnrtvx':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\%c'" % i):
check(b"\\" + b, b"\\" + b)
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\%c'" % (i-32)):
check(b"\\" + b.upper(), b"\\" + b.upper())
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\8'"):
check(br"\8", b"\\8")
with self.assertWarns(DeprecationWarning):
check(br"\9", b"\\9")
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\\xfa'") as cm:
check(b"\\\xfa", b"\\\xfa")
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\z'"):
+ self.assertEqual(decode(br'\x\z', 'ignore'), (b'\\z', 4))
+
def test_errors(self):
decode = codecs.escape_decode
self.assertRaises(ValueError, decode, br"\x")
@@ -2393,20 +2405,31 @@ class UnicodeEscapeTest(ReadTest, unitte
check(br"[\x410]", "[A0]")
check(br"\u20ac", "\u20ac")
check(br"\U0001d120", "\U0001d120")
+
+ def test_decode_warnings(self):
+ decode = codecs.unicode_escape_decode
+ check = coding_checker(self, decode)
for i in range(97, 123):
b = bytes([i])
if b not in b'abfnrtuvx':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\%c'" % i):
check(b"\\" + b, "\\" + chr(i))
if b.upper() not in b'UN':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\%c'" % (i-32)):
check(b"\\" + b.upper(), "\\" + chr(i-32))
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\8'"):
check(br"\8", "\\8")
with self.assertWarns(DeprecationWarning):
check(br"\9", "\\9")
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\\xfa'") as cm:
check(b"\\\xfa", "\\\xfa")
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"invalid escape sequence '\\z'"):
+ self.assertEqual(decode(br'\x\z', 'ignore'), ('\\z', 4))
def test_decode_errors(self):
decode = codecs.unicode_escape_decode
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst
@@ -0,0 +1,2 @@
+Fix use-after-free in the "unicode-escape" decoder with a non-"strict" error
+handler.
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1060,10 +1060,11 @@ _PyBytes_FormatEx(const char *format, Py
}
/* Unescape a backslash-escaped string. */
-PyObject *_PyBytes_DecodeEscape(const char *s,
+PyObject *_PyBytes_DecodeEscape2(const char *s,
Py_ssize_t len,
const char *errors,
- const char **first_invalid_escape)
+ int *first_invalid_escape_char,
+ const char **first_invalid_escape_ptr)
{
int c;
char *p;
@@ -1077,7 +1078,8 @@ PyObject *_PyBytes_DecodeEscape(const ch
return NULL;
writer.overallocate = 1;
- *first_invalid_escape = NULL;
+ *first_invalid_escape_char = -1;
+ *first_invalid_escape_ptr = NULL;
end = s + len;
while (s < end) {
@@ -1152,9 +1154,10 @@ PyObject *_PyBytes_DecodeEscape(const ch
break;
default:
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-1; /* Back up one char, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = (unsigned char)s[-1];
+ /* Back up one char, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 1;
}
*p++ = '\\';
s--;
@@ -1168,21 +1171,36 @@ PyObject *_PyBytes_DecodeEscape(const ch
return NULL;
}
+// Export for binary compatibility.
+PyObject *_PyBytes_DecodeEscape(const char *s,
+ Py_ssize_t len,
+ const char *errors,
+ const char **first_invalid_escape)
+{
+ int first_invalid_escape_char;
+ return _PyBytes_DecodeEscape2(
+ s, len, errors,
+ &first_invalid_escape_char,
+ first_invalid_escape);
+}
+
PyObject *PyBytes_DecodeEscape(const char *s,
Py_ssize_t len,
const char *errors,
Py_ssize_t Py_UNUSED(unicode),
const char *Py_UNUSED(recode_encoding))
{
- const char* first_invalid_escape;
- PyObject *result = _PyBytes_DecodeEscape(s, len, errors,
- &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyBytes_DecodeEscape2(s, len, errors,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL)
return NULL;
- if (first_invalid_escape != NULL) {
+ if (first_invalid_escape_char != -1) {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"invalid escape sequence '\\%c'",
- (unsigned char)*first_invalid_escape) < 0) {
+ first_invalid_escape_char) < 0) {
Py_DECREF(result);
return NULL;
}
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -6278,20 +6278,23 @@ PyUnicode_AsUTF16String(PyObject *unicod
static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL;
PyObject *
-_PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
+_PyUnicode_DecodeUnicodeEscapeInternal2(const char *s,
Py_ssize_t size,
const char *errors,
Py_ssize_t *consumed,
- const char **first_invalid_escape)
+ int *first_invalid_escape_char,
+ const char **first_invalid_escape_ptr)
{
const char *starts = s;
+ const char *initial_starts = starts;
_PyUnicodeWriter writer;
const char *end;
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
// so we can remember if we've seen an invalid escape char or not
- *first_invalid_escape = NULL;
+ *first_invalid_escape_char = -1;
+ *first_invalid_escape_ptr = NULL;
if (size == 0) {
if (consumed) {
@@ -6474,9 +6477,12 @@ _PyUnicode_DecodeUnicodeEscapeInternal(c
goto error;
default:
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-1; /* Back up one char, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = c;
+ if (starts == initial_starts) {
+ /* Back up one char, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 1;
+ }
}
WRITE_ASCII_CHAR('\\');
WRITE_CHAR(c);
@@ -6515,22 +6521,39 @@ _PyUnicode_DecodeUnicodeEscapeInternal(c
return NULL;
}
+// Export for binary compatibility.
+PyObject *
+_PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
+ Py_ssize_t size,
+ const char *errors,
+ Py_ssize_t *consumed,
+ const char **first_invalid_escape)
+{
+ int first_invalid_escape_char;
+ return _PyUnicode_DecodeUnicodeEscapeInternal2(
+ s, size, errors, consumed,
+ &first_invalid_escape_char,
+ first_invalid_escape);
+}
+
PyObject *
_PyUnicode_DecodeUnicodeEscapeStateful(const char *s,
Py_ssize_t size,
const char *errors,
Py_ssize_t *consumed)
{
- const char *first_invalid_escape;
- PyObject *result = _PyUnicode_DecodeUnicodeEscapeInternal(s, size, errors,
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyUnicode_DecodeUnicodeEscapeInternal2(s, size, errors,
consumed,
- &first_invalid_escape);
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL)
return NULL;
- if (first_invalid_escape != NULL) {
+ if (first_invalid_escape_char != -1) {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"invalid escape sequence '\\%c'",
- (unsigned char)*first_invalid_escape) < 0) {
+ first_invalid_escape_char) < 0) {
Py_DECREF(result);
return NULL;
}
--- a/Parser/pegen/parse_string.c
+++ b/Parser/pegen/parse_string.c
@@ -119,12 +119,15 @@ decode_unicode_with_escapes(Parser *pars
len = p - buf;
s = buf;
- const char *first_invalid_escape;
- v = _PyUnicode_DecodeUnicodeEscapeInternal(s, len, NULL, NULL, &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ v = _PyUnicode_DecodeUnicodeEscapeInternal2(s, (Py_ssize_t)len, NULL, NULL,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
- if (v != NULL && first_invalid_escape != NULL) {
- if (warn_invalid_escape_sequence(parser, *first_invalid_escape, t) < 0) {
- /* We have not decref u before because first_invalid_escape points
+ if (v != NULL && first_invalid_escape_ptr != NULL) {
+ if (warn_invalid_escape_sequence(parser, *first_invalid_escape_ptr, t) < 0) {
+ /* We have not decref u before because first_invalid_escape_ptr points
inside u. */
Py_XDECREF(u);
Py_DECREF(v);
@@ -138,14 +141,17 @@ decode_unicode_with_escapes(Parser *pars
static PyObject *
decode_bytes_with_escapes(Parser *p, const char *s, Py_ssize_t len, Token *t)
{
- const char *first_invalid_escape;
- PyObject *result = _PyBytes_DecodeEscape(s, len, NULL, &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyBytes_DecodeEscape2(s, len, NULL,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL) {
return NULL;
}
- if (first_invalid_escape != NULL) {
- if (warn_invalid_escape_sequence(p, *first_invalid_escape, t) < 0) {
+ if (first_invalid_escape_ptr != NULL) {
+ if (warn_invalid_escape_sequence(p, *first_invalid_escape_ptr, t) < 0) {
Py_DECREF(result);
return NULL;
}

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8c136d199d3637a1fce98a16adc809c1d83c922d02d41f3614b34f8b6e7d38ec
size 19652572

File diff suppressed because one or more lines are too long

View File

@ -1,141 +1,3 @@
-------------------------------------------------------------------
Thu May 22 13:01:17 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2025-4516-DecodeError-handler.patch fixing
CVE-2025-4516 (bsc#1243273) blocking DecodeError handling
vulnerability, which could lead to DoS.
-------------------------------------------------------------------
Sat May 10 11:38:21 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Remove python-3.3.0b1-test-posix_fadvise.patch (not needed
since kernel 3.6-rc1)
-------------------------------------------------------------------
Wed Apr 9 20:04:17 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Update to 3.9.22:
- gh-131809: Update bundled libexpat to 2.7.1
- gh-131261: Upgrade to libexpat 2.7.0
- gh-105704: When using urllib.parse.urlsplit() and
urllib.parse.urlparse() host parsing would not reject domain
names containing square brackets ([ and ]). Square brackets
are only valid for IPv6 and IPvFuture hosts according to RFC
3986 Section 3.2.2 (bsc#1236705, CVE-2025-0938,
gh#python/cpython#105704).
- gh-121284: Fix bug in the folding of rfc2047 encoded-words
when flattening an email message using a modern email
policy. Previously when an encoded-word was too long for
a line, it would be decoded, split across lines, and
re-encoded. But commas and other special characters in the
original text could be left unencoded and unquoted. This
could theoretically be used to spoof header lines using a
carefully constructed encoded-word if the resulting rendered
email was transmitted or re-parsed.
- gh-119511: Fix a potential denial of service in the imaplib
module. When connecting to a malicious server, it could
cause an arbitrary amount of memory to be allocated. On many
systems this is harmless as unused virtual memory is only
a mapping, but if this hit a virtual address size limit
it could lead to a MemoryError or other process crash. On
unusual systems or builds where all allocated memory is
touched and backed by actual ram or storage it couldve
consumed resources doing so until similarly crashing.
- gh-121277: Writers of CPythons documentation can now use
next as the version for the versionchanged, versionadded,
deprecated directives.
- Remote upstreamed patch:
- CVE-2025-0938-sq-brackets-domain-names.patch
-------------------------------------------------------------------
Mon Mar 10 15:44:31 UTC 2025 - Bernhard Wiedemann <bwiedemann@suse.com>
- Skip PGO with %want_reproducible_builds (bsc#1239210)
-------------------------------------------------------------------
Tue Feb 4 14:43:13 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2025-0938-sq-brackets-domain-names.patch which
disallows square brackets ([ and ]) in domain names for parsed
URLs (bsc#1236705, CVE-2025-0938, gh#python/cpython#105704)
-------------------------------------------------------------------
Wed Dec 4 19:51:41 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update to 3.9.21:
- Tests
- gh-125041: Re-enable skipped tests for zlib on the
s390x architecture: only skip checks of the compressed
bytes, which can be different between zlibs software
implementation and the hardware-accelerated implementation.
- gh-109396: Fix test_socket.test_hmac_sha1() in FIPS
mode. Use a longer key: FIPS mode requires at least of at
least 112 bits. The previous key was only 32 bits. Patch by
Victor Stinner.
- gh-100454: Fix SSL tests CI for OpenSSL 3.1+
- Security
- gh-126623: Upgrade libexpat to 2.6.4
- gh-122792: Changed IPv4-mapped ipaddress.IPv6Address to
consistently use the mapped IPv4 address value for deciding
properties. Properties which have their behavior fixed are
is_multicast, is_reserved, is_link_local, is_global, and
is_unspecified (bsc#1233307, CVE-2024-11168).
- Library
- gh-124651: Properly quote template strings in venv
activation scripts (bsc#1232241, CVE-2024-9287).
- gh-103848: Add checks to ensure that [ bracketed ] hosts
found by urllib.parse.urlsplit() are of IPv6 or IPvFuture
format.
- Documentation
- gh-95588: Clarified the conflicting advice given in the ast
documentation about ast.literal_eval() being “safe” for use
on untrusted input while at the same time warning that it
can crash the process. The latter statement is true and is
deemed unfixable without a large amount of work unsuitable
for a bugfix. So we keep the warning and no longer claim
that literal_eval is safe.
- Remove upstreamed patches:
- CVE-2024-11168-validation-IPv6-addrs.patch
- CVE-2024-9287-venv_path_unquoted.patch
-------------------------------------------------------------------
Thu Nov 14 07:06:20 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Remove -IVendor/ from python-config boo#1231795
-------------------------------------------------------------------
Wed Nov 13 13:25:01 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-11168-validation-IPv6-addrs.patch
fixing bsc#1233307 (CVE-2024-11168,
gh#python/cpython#103848): Improper validation of IPv6 and
IPvFuture addresses.
-------------------------------------------------------------------
Fri Nov 1 21:16:32 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Update CVE-2024-9287-venv_path_unquoted.patch according to the
upstream PR gh#python/cpython!126301.
-------------------------------------------------------------------
Thu Oct 24 16:09:00 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
path names provided when creating a virtual environment
(bsc#1232241, CVE-2024-9287)
-------------------------------------------------------------------
Wed Oct 2 16:18:29 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Drop .pyc files from docdir for reproducible builds
(bsc#1230906).
-------------------------------------------------------------------
Fri Sep 20 14:57:10 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add sphinx-802.patch to overcome working both with the most
recent and older Sphinx versions.
-------------------------------------------------------------------
Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
@ -172,7 +34,7 @@ Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
:class:`zipfile.Path` causing infinite loops (gh-122905) without breaking
contents using legitimate characters (bsc#1229704, CVE-2024-8088).
- gh-123067: Fix quadratic complexity in parsing ``"``-quoted cookie values
with backslashes by :mod:`http.cookies` (bsc#1229596, CVE-2024-7592).
with backslashes by :mod:`http.cookies`.
- gh-121650: :mod:`email` headers with embedded newlines are now quoted on
output. The :mod:`~email.generator` will now refuse to serialize (write)
headers that are unsafely folded or delimited; see
@ -214,7 +76,8 @@ Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
Thu Sep 5 13:44:48 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Add CVE-2024-6232-cookies-quad-complex.patch to avoid quadratic
complexity in parsing tarfile headers (bsc#1230227, CVE-2024-6232).
complexity in parsing "-quoted cookie values with backslashes
(bsc#1229596, CVE-2024-6232).
-------------------------------------------------------------------
Thu Sep 5 08:11:45 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
@ -361,12 +224,12 @@ Fri Feb 23 01:06:42 UTC 2024 - Matej Cepl <mcepl@suse.com>
- Repurpose skip-failing-tests.patch to increase timeout for
test.test_asyncio.test_tasks.TimeoutTests.test_timeout_time,
which fails on slow machines in IBS (s390x).
-------------------------------------------------------------------
Tue Feb 20 22:14:02 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
- Remove double definition of /usr/bin/idle%%{version} in
%%files.
%%files.
-------------------------------------------------------------------
Thu Feb 15 10:29:07 UTC 2024 - Daniel Garcia <daniel.garcia@suse.com>
@ -505,7 +368,7 @@ Wed May 3 14:09:37 UTC 2023 - Matej Cepl <mcepl@suse.com>
-------------------------------------------------------------------
Tue Apr 18 05:00:11 UTC 2023 - Steve Kowalik <steven.kowalik@suse.com>
- Use python3 modules to build the documentation.
- Use python3 modules to build the documentation.
-------------------------------------------------------------------
Wed Mar 1 14:43:31 UTC 2023 - Matej Cepl <mcepl@suse.com>
@ -1078,7 +941,7 @@ Sat Mar 26 22:22:24 UTC 2022 - Matej Cepl <mcepl@suse.com>
Tue Feb 22 05:53:06 UTC 2022 - Steve Kowalik <steven.kowalik@suse.com>
- Add patch support-expat-245.patch:
* Support Expat >= 2.4.5
* Support Expat >= 2.4.5
-------------------------------------------------------------------
Wed Jan 19 21:50:04 UTC 2022 - Matej Cepl <mcepl@suse.com>
@ -1521,7 +1384,7 @@ Sat Jun 5 21:21:38 UTC 2021 - Matej Cepl <mcepl@suse.com>
-------------------------------------------------------------------
Fri Jun 4 21:36:30 UTC 2021 - Dirk Müller <dmueller@suse.com>
- allow build with Sphinx >= 3.x
- allow build with Sphinx >= 3.x
-------------------------------------------------------------------
Wed Jun 2 13:12:04 UTC 2021 - Dan Čermák <dcermak@suse.com>
@ -2073,7 +1936,7 @@ Sat Dec 12 14:29:33 UTC 2020 - Matej Cepl <mcepl@suse.com>
Thu Dec 10 00:26:51 UTC 2020 - Benjamin Greiner <code@bnavigator.de>
- Last try before this results in an editwar:
* remove importlib_resources and importlib-metadata
* remove importlib_resources and importlib-metadata
provides/obsoletes
* import importlib_resources is not the same as
import importlib.resources, same for metadata
@ -2190,54 +2053,54 @@ Tue Jul 21 09:53:06 UTC 2020 - Callum Farmer <callumjfarmer13@gmail.com>
- Removed CVE-2019-20907_tarfile-inf-loop.patch: fixed in upstream
- Removed recursion.tar: contained in upstream
- Update to 3.9.0b5:
- bpo-41304: Fixes python3x._pth being ignored on Windows, caused
- bpo-41304: Fixes python3x._pth being ignored on Windows, caused
by the fix for bpo-29778 (CVE-2020-15801).
- bpo-41162: Audit hooks are now cleared later during
finalization to avoid missing events.
- bpo-29778: Ensure python3.dll is loaded from correct locations
- bpo-29778: Ensure python3.dll is loaded from correct locations
when Python is embedded (CVE-2020-15523).
- bpo-39603: Prevent http header injection by rejecting control
- bpo-39603: Prevent http header injection by rejecting control
characters in http.client.putrequest(…).
- bpo-41295: Resolve a regression in CPython 3.8.4 where defining
“__setattr__” in a multi-inheritance setup and
“__setattr__” in a multi-inheritance setup and
calling up the hierarchy chain could fail if builtins/extension
types were involved in the base types.
- bpo-41247: Always cache the running loop holder when running
- bpo-41247: Always cache the running loop holder when running
asyncio.set_running_loop.
- bpo-41252: Fix incorrect refcounting in
- bpo-41252: Fix incorrect refcounting in
_ssl.cs _servername_callback().
- bpo-41215: Use non-NULL default values in the PEG parser
- bpo-41215: Use non-NULL default values in the PEG parser
keyword list to overcome a bug that was '
preventing Python from being properly compiled when using the
XLC compiler. Patch by Pablo Galindo.
- bpo-41218: Python 3.8.3 had a regression where compiling with
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT would
- bpo-41218: Python 3.8.3 had a regression where compiling with
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT would
aggressively mark list comprehension with CO_COROUTINE. Now only
list comprehension making use of async/await will tagged as so.
- bpo-41175: Guard against a NULL pointer dereference within
- bpo-41175: Guard against a NULL pointer dereference within
bytearrayobject triggered by the bytearray() + bytearray() operation.
- bpo-39960: The “hackcheck” that prevents sneaking around a types
__setattr__() by calling the superclass method was
- bpo-39960: The “hackcheck” that prevents sneaking around a types
__setattr__() by calling the superclass method was
rewritten to allow C implemented heap types.
- bpo-41288: Unpickling invalid NEWOBJ_EX opcode with the
- bpo-41288: Unpickling invalid NEWOBJ_EX opcode with the
C implementation raises now UnpicklingError instead of crashing.
- bpo-39017: Avoid infinite loop when reading specially crafted
- bpo-39017: Avoid infinite loop when reading specially crafted
TAR files using the tarfile module (CVE-2019-20907, bsc#1174091).
- bpo-41235: Fix the error handling in ssl.SSLContext.load_dh_params().
- bpo-41207: In distutils.spawn, restore expectation that
- bpo-41207: In distutils.spawn, restore expectation that
DistutilsExecError is raised when the command is not found.
- bpo-39168: Remove the __new__ method of typing.Generic.
- bpo-41194: Fix a crash in the _ast module: it can no longer be
- bpo-41194: Fix a crash in the _ast module: it can no longer be
loaded more than once. It now uses a global state rather than a module state.
- bpo-39384: Fixed email.contentmanager to allow set_content() to set a
- bpo-39384: Fixed email.contentmanager to allow set_content() to set a
null string.
- bpo-41300: Save files with non-ascii chars.
- bpo-41300: Save files with non-ascii chars.
Fix regression released in 3.9.0b4 and 3.8.4.
- bpo-37765: Add keywords to module name completion list.
- bpo-37765: Add keywords to module name completion list.
Rewrite Completions section of IDLE doc.
- bpo-40170: Revert PyType_HasFeature() change: it reads
again directly the PyTypeObject.tp_flags
member when the limited C API is not used, rather than always calling
- bpo-40170: Revert PyType_HasFeature() change: it reads
again directly the PyTypeObject.tp_flags
member when the limited C API is not used, rather than always calling
PyType_GetFlags() which hides implementation details.
-------------------------------------------------------------------
@ -2758,7 +2621,7 @@ Wed Jun 5 12:19:09 CEST 2019 - Matej Cepl <mcepl@suse.com>
pickling costs between processes
- typed_ast is merged back to CPython
- LOAD_GLOBAL is now 40% faster
- pickle now uses Protocol 4 by default, improving performance
- pickle now uses Protocol 4 by default, improving performance
- Remove patches which were included in the upstream:
- 00251-change-user-install-location.patch
- 00316-mark-bdist_wininst-unsupported.patch
@ -2903,7 +2766,7 @@ Mon Dec 17 17:24:49 CET 2018 - mcepl@suse.com
- Upgrade to 3.7.2rc1:
* bugfix release, for the full list of all changes see
https://docs.python.org/3.7/whatsnew/changelog.html#changelog
https://docs.python.org/3.7/whatsnew/changelog.html#changelog
- Make run of the test suite more verbose
-------------------------------------------------------------------
@ -3330,7 +3193,7 @@ Mon Mar 13 14:04:22 UTC 2017 - jmatejek@suse.com
Sat Feb 25 20:55:57 UTC 2017 - bwiedemann@suse.com
- Add 0001-allow-for-reproducible-builds-of-python-packages.patch
upstream https://github.com/python/cpython/pull/296
upstream https://github.com/python/cpython/pull/296
-------------------------------------------------------------------
Wed Feb 8 12:30:20 UTC 2017 - jmatejek@suse.com
@ -3396,7 +3259,7 @@ Mon Mar 7 20:38:11 UTC 2016 - toddrme2178@gmail.com
- Add Python-3.5.1-fix_lru_cache_copying.patch
Fix copying the lru_cache() wrapper object.
Fixes deep-copying lru_cache regression, which worked on
Fixes deep-copying lru_cache regression, which worked on
previous versions of python but fails on python 3.5.
This fixes a bunch of packages in devel:languages:python3.
See: https://bugs.python.org/issue25447
@ -3534,7 +3397,7 @@ Sun Jan 11 13:01:30 UTC 2015 - p.drouand@gmail.com
-------------------------------------------------------------------
Sat Oct 18 20:14:54 UTC 2014 - crrodriguez@opensuse.org
- Only pkgconfig(x11) is required for build, not the whole
- Only pkgconfig(x11) is required for build, not the whole
set of packages provided by xorg-x11-devel metapackage.
-------------------------------------------------------------------
@ -3594,7 +3457,7 @@ Wed Mar 26 15:24:46 UTC 2014 - jmatejek@suse.com
-------------------------------------------------------------------
Mon Mar 24 17:29:31 UTC 2014 - dmueller@suse.com
- remove blacklisting of test_posix on aarch64: qemu bug is fixed
- remove blacklisting of test_posix on aarch64: qemu bug is fixed
-------------------------------------------------------------------
Mon Mar 17 18:26:58 UTC 2014 - jmatejek@suse.com
@ -3697,7 +3560,7 @@ Tue Nov 19 14:28:41 UTC 2013 - jmatejek@suse.com
-------------------------------------------------------------------
Tue Oct 15 17:44:08 UTC 2013 - crrodriguez@opensuse.org
- build with -DOPENSSL_LOAD_CONF for the same reasons
- build with -DOPENSSL_LOAD_CONF for the same reasons
described in the python2 package.
-------------------------------------------------------------------
@ -3709,7 +3572,7 @@ Fri Aug 16 11:35:15 UTC 2013 - jmatejek@suse.com
-------------------------------------------------------------------
Thu Aug 8 14:54:49 UTC 2013 - dvaleev@suse.com
- Exclue test_faulthandler from tests on powerpc due to bnc#831629
- Exclue test_faulthandler from tests on powerpc due to bnc#831629
-------------------------------------------------------------------
Thu Jun 13 15:05:34 UTC 2013 - jmatejek@suse.com
@ -3768,7 +3631,7 @@ Fri Mar 1 07:42:21 UTC 2013 - dmueller@suse.com
- add ctypes-libffi-aarch64.patch:
* import aarch64 support for libffi in _ctypes module
- add aarch64 to the list of lib64 based archs
- add aarch64 to the list of lib64 based archs
- add movetogetdents64.diff:
* port to getdents64, as SYS_getdents is not implemented everywhere
@ -3822,9 +3685,9 @@ Mon Oct 29 18:21:45 UTC 2012 - dmueller@suse.com
-------------------------------------------------------------------
Thu Oct 25 08:14:36 UTC 2012 - Rene.vanPaassen@gmail.com
- exclude test_math for SLE 11; math library fails on negative
- exclude test_math for SLE 11; math library fails on negative
gamma function values close to integers and 0, probably
due to imprecision in -lm on SLE_11_SP2.
due to imprecision in -lm on SLE_11_SP2.
-------------------------------------------------------------------
Tue Oct 16 12:15:34 UTC 2012 - coolo@suse.com
@ -3848,7 +3711,7 @@ Mon Oct 1 08:53:03 UTC 2012 - idonmez@suse.com
-------------------------------------------------------------------
Thu Sep 27 12:35:01 UTC 2012 - idonmez@suse.com
- Correct dependency for python3-testsuite,
- Correct dependency for python3-testsuite,
python3-tkinter -> python3-tk
-------------------------------------------------------------------
@ -3881,7 +3744,7 @@ Fri Aug 3 12:09:34 UTC 2012 - jmatejek@suse.com
-------------------------------------------------------------------
Fri Jul 27 09:02:41 UTC 2012 - dvaleev@suse.com
- skip test_io on ppc
- skip test_io on ppc
- drop test_io ppc patch
-------------------------------------------------------------------
@ -3930,8 +3793,8 @@ Wed Jan 18 15:49:47 UTC 2012 - jmatejek@suse.com
-------------------------------------------------------------------
Sun Dec 25 13:25:01 UTC 2011 - idonmez@suse.com
- Use system ffi, included one is broken see
http://bugs.python.org/issue11729 and
- Use system ffi, included one is broken see
http://bugs.python.org/issue11729 and
http://bugs.python.org/issue12081
-------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
#
# spec file for package python39
#
# Copyright (c) 2025 SUSE LLC
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -36,7 +36,7 @@
%bcond_without general
%endif
%if 0%{?do_profiling} && !0%{?want_reproducible_builds}
%if 0%{?do_profiling}
%bcond_without profileopt
%else
%bcond_with profileopt
@ -99,13 +99,13 @@
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
%bcond_without profileopt
Name: %{python_pkg_name}%{psuffix}
Version: 3.9.22
Version: 3.9.20
Release: 0
Summary: Python 3 Interpreter
License: Python-2.0
URL: https://www.python.org/
Source0: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.sigstore
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.asc
Source2: baselibs.conf
Source3: README.SUSE
Source7: macros.python3
@ -134,6 +134,10 @@ Source100: PACKAGING-NOTES
# to /usr/local if executable is /usr/bin/python* and RPM build
# is not detected to make pip and distutils install into separate location
Patch02: F00251-change-user-install-location.patch
# PATCH-FEATURE-UPSTREAM decimal.patch bsc#1189356 mcepl@suse.com
# fix building with mpdecimal
# https://www.bytereef.org/contrib/decimal.diff
Patch05: decimal.patch
# PATCH-FEATURE-UPSTREAM distutils-reproducible-compile.patch gh#python/cpython#8057 mcepl@suse.com
# Improve reproduceability
Patch06: distutils-reproducible-compile.patch
@ -141,6 +145,8 @@ Patch06: distutils-reproducible-compile.patch
Patch07: python-3.3.0b1-localpath.patch
# replace DATE, TIME and COMPILER by fixed definitions to aid reproducible builds
Patch08: python-3.3.0b1-fix_date_time_compiler.patch
# POSIX_FADV_WILLNEED throws EINVAL. Use a different constant in test
Patch09: python-3.3.0b1-test-posix_fadvise.patch
# Raise timeout value for test_subprocess
Patch15: subprocess-raise-timeout.patch
Patch25: python3-imp-returntype.patch
@ -155,46 +161,37 @@ Patch33: no-skipif-doctests.patch
# PATCH-FIX-SLE skip-test_pyobject_freed_is_freed.patch mcepl@suse.com
# skip a test failing on SLE-15
Patch34: skip-test_pyobject_freed_is_freed.patch
# PATCH-FEATURE-UPSTREAM decimal.patch bsc#1189356 mcepl@suse.com
# fix building with mpdecimal
# https://www.bytereef.org/contrib/decimal.diff
Patch35: decimal.patch
# PATCH-FIX-UPSTREAM support-expat-CVE-2022-25236-patched.patch jsc#SLE-21253 mcepl@suse.com
# Makes Python resilient to changes of API of libexpat
Patch40: support-expat-CVE-2022-25236-patched.patch
Patch35: support-expat-CVE-2022-25236-patched.patch
# PATCH-FIX-UPSTREAM CVE-2023-52425-libexpat-2.6.0-backport.patch gh#python/cpython#117187 mcepl@suse.com
# Make the test suite work with libexpat < 2.6.0
Patch41: CVE-2023-52425-libexpat-2.6.0-backport.patch
Patch36: CVE-2023-52425-libexpat-2.6.0-backport.patch
# PATCH-FIX-UPSTREAM 98437-sphinx.locale._-as-gettext-in-pyspecific.patch gh#python/cpython#98366 mcepl@suse.com
# this patch makes things totally awesome
Patch42: 98437-sphinx.locale._-as-gettext-in-pyspecific.patch
Patch37: 98437-sphinx.locale._-as-gettext-in-pyspecific.patch
# PATCH-FIX-UPSTREAM bpo-37596-make-set-marshalling.patch bsc#1211765 mcepl@suse.com
# Make `set` and `frozenset` marshalling deterministic
Patch43: bpo-37596-make-set-marshalling.patch
Patch38: bpo-37596-make-set-marshalling.patch
# PATCH-FIX-UPSTREAM gh-78214-marshal_stabilize_FLAG_REF.patch bsc#1213463 mcepl@suse.com
# marshal: Stabilize FLAG_REF usage
Patch44: gh-78214-marshal_stabilize_FLAG_REF.patch
Patch39: gh-78214-marshal_stabilize_FLAG_REF.patch
# PATCH-FIX-UPSTREAM 99366-patch.dict-can-decorate-async.patch bsc#[0-9]+ mcepl@suse.com
# Patch for gh#python/cpython#98086
Patch45: 99366-patch.dict-can-decorate-async.patch
Patch40: 99366-patch.dict-can-decorate-async.patch
# PATCH-FIX-OPENSUSE downport-Sphinx-features.patch mcepl@suse.com
# Make documentation build with older Sphinx
Patch46: downport-Sphinx-features.patch
Patch41: downport-Sphinx-features.patch
# PATCH-FIX-UPSTREAM bso1227999-reproducible-builds.patch bsc#1227999 mcepl@suse.com
# reproducibility patches
Patch47: bso1227999-reproducible-builds.patch
Patch46: bso1227999-reproducible-builds.patch
# PATCH-FIX-UPSTREAM CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch bsc#1227233 mcepl@suse.com
# Remove for support for anything but OpenSSL 1.1.1 or newer
Patch48: CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch
# PATCH-FIX-UPSTREAM gh120226-fix-sendfile-test-kernel-610.patch gh#python/cpython#120226 mcepl@suse.com
# Fix test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 (GH-120227)
Patch50: gh120226-fix-sendfile-test-kernel-610.patch
# PATCH-FIX-UPSTREAM sphinx-802.patch mcepl@suse.com
# status_iterator method moved between the Sphinx versions
Patch51: sphinx-802.patch
# PATCH-FIX-UPSTREAM CVE-2025-4516-DecodeError-handler.patch bsc#1243273 mcepl@suse.com
# this patch makes things totally awesome
Patch52: CVE-2025-4516-DecodeError-handler.patch
BuildRequires: autoconf-archive
BuildRequires: automake
BuildRequires: fdupes
@ -433,40 +430,34 @@ other applications.
%prep
%setup -q -n %{tarname}
%patch -p1 -P 02
%patch -p1 -P 06
%patch -p1 -P 07
%patch -p1 -P 08
%patch -p1 -P 15
%patch -p1 -P 25
%patch -p1 -P 29
%patch -p1 -P 32
%patch -P 02 -p1
%patch -P 06 -p1
%patch -P 07 -p1
%patch -P 08 -p1
%patch -P 09 -p1
%patch -P 15 -p1
%patch -P 25 -p1
%patch -P 29 -p1
%patch -P 32 -p1
%if 0%{?sle_version}
%patch -p1 -P 33
%patch -p1 -P 34
%patch -P 33 -p1
%patch -P 34 -p1
%endif
%if %{with mpdecimal}
%patch -p1 -P 35
%patch -P 05 -p1
%endif
%patch -p1 -P 40
%patch -p1 -P 41
%patch -p1 -P 42
%patch -p1 -P 43
%patch -p1 -P 44
%patch -p1 -P 45
%patch -P 35 -p1
%patch -P 36 -p1
%patch -P 37 -p1
%patch -P 38 -p1
%patch -P 39 -p1
%patch -P 40 -p1
%if 0%{?sle_version} && 0%{?sle_version} <= 150500
%patch -p1 -P 46
%patch -p1 -P 41
%endif
%patch -p1 -P 47
%patch -p1 -P 46
%patch -p1 -P 48
%patch -p1 -P 50
%patch -p1 -P 51
%patch -p1 -P 52
# drop Autoconf version requirement
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
@ -773,9 +764,6 @@ install -m 755 -D Tools/gdb/libpython.py %{buildroot}%{_datadir}/gdb/auto-load/%
# install devel files to /config
#cp Makefile Makefile.pre.in Makefile.pre $RPM_BUILD_ROOT%{sitedir}/config-%{python_abi}/
# Remove -IVendor/ from python-config boo#1231795
sed -i 's/-IVendor\///' %{buildroot}%{_bindir}/python%{python_abi}-config
# RPM macros
%if %{primary_interpreter}
mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
@ -804,11 +792,6 @@ LD_LIBRARY_PATH=. ./python -O -c "from py_compile import compile; compile('$FAIL
echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-import-failed-hooks.pth
%endif
# For the purposes of reproducibility, it is necessary to eliminate any *.pyc files inside documentation dirs
if [ -d %{buildroot}%{_defaultdocdir} ] ; then
find %{buildroot}%{_defaultdocdir} -type f -name \*.pyc -ls -exec rm -vf '{}' \;
fi
%if %{with general}
%files -n %{python_pkg_name}-tk
%{sitedir}/tkinter

View File

@ -1,23 +0,0 @@
---
Doc/tools/extensions/pyspecific.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
===================================================================
--- Python-3.9.22.orig/Doc/tools/extensions/pyspecific.py 2025-04-11 09:50:56.818993764 +0200
+++ Python-3.9.22/Doc/tools/extensions/pyspecific.py 2025-04-11 09:51:18.844485631 +0200
@@ -28,7 +28,13 @@
except ImportError:
from sphinx.environment import NoUri
from sphinx.locale import _ as sphinx_gettext
-from sphinx.util import status_iterator, logging
+try:
+ from sphinx.util.display import status_iterator
+except ImportError:
+ # This method was moved into sphinx.util.display in Sphinx 6.1.0. Before
+ # that it resided in sphinx.util.
+ from sphinx.util import status_iterator
+from sphinx.util import logging
from sphinx.util.nodes import split_explicit_title
from sphinx.writers.text import TextWriter, TextTranslator
from sphinx.writers.latex import LaTeXTranslator

View File

@ -2,11 +2,9 @@
Doc/tools/extensions/pyspecific.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py
===================================================================
--- Python-3.9.22.orig/Doc/tools/extensions/pyspecific.py 2025-04-08 17:21:55.000000000 +0200
+++ Python-3.9.22/Doc/tools/extensions/pyspecific.py 2025-04-11 09:49:58.417019238 +0200
@@ -407,7 +407,12 @@
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -385,7 +385,12 @@ class DeprecatedRemoved(Directive):
translatable=False)
node.append(para)
env = self.state.document.settings.env