diff --git a/CVE-2025-4516-DecodeError-handler.patch b/CVE-2025-4516-DecodeError-handler.patch deleted file mode 100644 index a8b554d..0000000 --- a/CVE-2025-4516-DecodeError-handler.patch +++ /dev/null @@ -1,426 +0,0 @@ -From 0d5d68f7075788b6912f8632dc841dca97ece409 Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -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 ---- - 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 = 'abcghi'*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; - } diff --git a/Python-3.9.22.tar.xz b/Python-3.9.22.tar.xz deleted file mode 100644 index d991e4e..0000000 --- a/Python-3.9.22.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c136d199d3637a1fce98a16adc809c1d83c922d02d41f3614b34f8b6e7d38ec -size 19652572 diff --git a/Python-3.9.22.tar.xz.sigstore b/Python-3.9.22.tar.xz.sigstore deleted file mode 100644 index e7470a7..0000000 --- a/Python-3.9.22.tar.xz.sigstore +++ /dev/null @@ -1 +0,0 @@ -{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzzCCAlWgAwIBAgIUF5l4z/m7U4YV9ObX9yrHVSrwtQIwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNDA4MTY0MDM2WhcNMjUwNDA4MTY1MDM2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKB5tIN2pdPcLI8+G/2PvFf5mNXRVX30+9UWQwD1XLtPM2SHNpdOXPTjAqC9BVr2lzSq0y0CBNWlQ7d8vTe7ctaOCAXQwggFwMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUkWbkA26gAO+nn/4RBqHwOJwqouYwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPbHVrYXN6QGxhbmdhLnBsMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABlhZGbmQAAAQDAEgwRgIhAL64P7MeYczG0eTPRtbKWh+JK3QONJeTX1Siu1QatF86AiEAgWJoJpZ5wnhvnNll68ZfS4A5NWZrmBQV1jNl6vWn31AwCgYIKoZIzj0EAwMDaAAwZQIwFisaGblldHezzUuq5dHK++zSJ0A+h+TLvlSsP5GortlcKRHvWpNpbNBEgIde2Jh9AjEAi1SXirGnti3TDZHPkuMPpdCT49lydH5aP8RlZfx279WUB5mbJLV+ckvS1lR/vL/S"}, "tlogEntries": [{"logIndex": "193991733", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1744130436", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQCZojFg3d0b1VlT1iIYzQD9qi0Gco8pMfY7ySidgb4VWAIgX2rTgPF7dLilPXnWN4zEd3ZCpuV6RDl8c42m+mok2ks="}, "inclusionProof": {"logIndex": "72087471", "rootHash": "q/PkICD5uDg5OlvIWNsF+lXN1ZiHEWNqVvtzFtmAPlk=", "treeSize": "72087476", "hashes": ["4yUybcYvtBlJ50W9AAsyNwk4NR+F6hiMzaeYCGGB1u8=", "1+97TstZdQ7MhyOhcTb/5wXWWmSsTbW39uY9kLhnhfo=", "q3YXOnHzg/M0HDq9vcHtAaCfgL1bSUam96gi2CbgGnk=", "kV8g3sPKmH7KgUIy4uT6+MtE52LZBdVAU2cDVyNekgU=", "SIo81b3kZgGsX/FWdBQYuvP5papZCszfK1URvAzEKDw=", "qSrXBipOR98Puq+IERBcOWHKeidS0RBLwd959YHA0D4=", "b7hTc5162/5hAKKTNfIy2OShk3XeVpGyGUwnpNrnRWg=", "GXs5uhC5teyVctnWE7ExxF5zLscIRrTKPGgu1U1Juec=", "SEpdK86t0h91343ndP33NAdKXC2lyurSAYMUT30LXYw=", "nATuuvI7Y38ODRIhealRzPKZWWvhMr6ltN0JKaAyLfM=", "TQThq+xH/Rys7mbboD00p4znY8nZ9kiJ56STr/CKVdw=", "7MlcOPugq/cko9b3dV9PgEuxQTnIJE5JYyv5V8MSoKg=", "Y0UveOhlrOl08kRY9fZBgfV5WllXxE42rV8NE+GgwCs=", "RgE76aZZETQ/ZXQCSka8ujxPpjA9SjPpXZFpkrF58Gk=", "+MDT1rEJIJ21rvjo6a7jzRPh//LjIcmfFhNEV/fA+jA=", "QReFEOB9XSZtDKsjRtA0fGnYGMYD2Z7qn50auG1YlWo=", "K26LG80DXyb+bC58c4Nw00WigG52v0PCsZGY3ExGsts=", "WEm5OgPzJpYROv+4CcrieexCYyQKrLUH3hbxmcQQ+DM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n72087476\nq/PkICD5uDg5OlvIWNsF+lXN1ZiHEWNqVvtzFtmAPlk=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiEAptmnbism1EAeeK49B0IwJz0Y3HYhyW39gnaBoHxVFQECICnFiKtwk9Wce+nL732qSHuv60Qt7s+aJJpXG9NB1c/7\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4YzEzNmQxOTlkMzYzN2ExZmNlOThhMTZhZGM4MDljMWQ4M2M5MjJkMDJkNDFmMzYxNGIzNGY4YjZlN2QzOGVjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRTVDSUJaNkEzZ2FsU1lTY1ByVEV2ZU1pcEpQMklwVE1uVHcwWWU1bkNpREFpQk9xaGlUZTFYbFJOanloZW5tS0ZGNzZrVm1PaDA5blpOdXFhWWx6ZjlGaXc9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZla05EUVd4WFowRjNTVUpCWjBsVlJqVnNOSG92YlRkVk5GbFdPVTlpV0RsNWNraFdVM0ozZEZGSmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVFUVRSTlZGa3dUVVJOTWxkb1kwNU5hbFYzVGtSQk5FMVVXVEZOUkUweVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZMUWpWMFNVNHljR1JRWTB4Sk9DdEhMekpRZGtabU5XMU9XRkpXV0RNd0t6bFZWMUVLZDBReFdFeDBVRTB5VTBoT2NHUlBXRkJVYWtGeFF6bENWbkl5YkhwVGNUQjVNRU5DVGxkc1VUZGtPSFpVWlRkamRHRlBRMEZZVVhkblowWjNUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZyVjJKckNrRXlObWRCVHl0dWJpODBVa0p4U0hkUFNuZHhiM1ZaZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlraFdjbGxZVGpaUlIzaG9ZbTFrYUV4dVFuTk5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVhkWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWprS1FraHpRV1ZSUWpOQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnNhRnBIWW0xUlFRcEJRVkZFUVVWbmQxSm5TV2hCVERZMFVEZE5aVmxqZWtjd1pWUlFVblJpUzFkb0swcExNMUZQVGtwbFZGZ3hVMmwxTVZGaGRFWTROa0ZwUlVGblYwcHZDa3B3V2pWM2JtaDJiazVzYkRZNFdtWlRORUUxVGxkYWNtMUNVVll4YWs1c05uWlhiak14UVhkRFoxbEpTMjlhU1hwcU1FVkJkMDFFWVVGQmQxcFJTWGNLUm1sellVZGliR3hrU0dWNmVsVjFjVFZrU0VzckszcFRTakJCSzJnclZFeDJiRk56VURWSGIzSjBiR05MVWtoMlYzQk9jR0pPUWtWblNXUmxNa3BvT1FwQmFrVkJhVEZUV0dseVIyNTBhVE5VUkZwSVVHdDFUVkJ3WkVOVU5EbHNlV1JJTldGUU9GSnNXbVo0TWpjNVYxVkNOVzFpU2t4V0syTnJkbE14YkZJdkNuWk1MMU1LTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "jBNtGZ02N6H86YoWrcgJwdg8ki0C1B82FLNPi259OOw="}, "signature": "MEQCIE5CIBZ6A3galSYScPrTEveMipJP2IpTMnTw0Ye5nCiDAiBOqhiTe1XlRNjyhenmKFF76kVmOh09nZNuqaYlzf9Fiw=="}} diff --git a/Python-3.9.23.tar.xz b/Python-3.9.23.tar.xz new file mode 100644 index 0000000..1edf267 --- /dev/null +++ b/Python-3.9.23.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61a42919e13d539f7673cf11d1c404380e28e540510860b9d242196e165709c9 +size 19659284 diff --git a/Python-3.9.23.tar.xz.sigstore b/Python-3.9.23.tar.xz.sigstore new file mode 100644 index 0000000..f3e8c70 --- /dev/null +++ b/Python-3.9.23.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIIC0DCCAlWgAwIBAgIUG229RKhIVHHNhr+bZV55P8F/JiYwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNjAzMTkyMDQ1WhcNMjUwNjAzMTkzMDQ1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHAdkk3GmQSTLHaA3qgs8Mto97OSVbVhaNbzSF2eatgDIKJUkUF9BFqx+RKVYbHU5FQJHdwA5T67OfhaDYHiyaqOCAXQwggFwMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUaB0HmIo69ITnU91ryuyAKS4hsbgwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPbHVrYXN6QGxhbmdhLnBsMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABlzc9LZwAAAQDAEgwRgIhAKVxDJnomsWJaXHsKKu19qVvfaPnwK5YQXGoI9SKn+NJAiEA+CLl5/VDMS+UMV8Nh+89J2zcpcypEhw6C4tW1BCCuDAwCgYIKoZIzj0EAwMDaQAwZgIxAICtnwUolcM1gk7JBamvFMSw9K1YXhTaErgTVTlJK+pVy7GnuG9sFdBAo1cu2l8KpwIxAPa0s2b6co6pQfHxXbTADBsp4WT6YmiW7A+92JlwY87vD+7dP1rKzW3NWRZOE5BnqQ=="}, "tlogEntries": [{"logIndex": "228949549", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1748978445", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQCNuRResQCE4b2mA5/+gTwctji/1qL67SbeaciSlgj6NQIgE7vY0Fdoem2aODoKaHoieIRo89rcg7mX2mZL3B/XYh8="}, "inclusionProof": {"logIndex": "107045287", "rootHash": "hgR6aB6kU+T1uo4iUx75tlIhKkYbUyPsHac2yhFgZpE=", "treeSize": "107045297", "hashes": ["31ltlTE5JIioyJ8rdH3OjwO9d3Us17sfd29GleLF5J0=", "AkqFsr2XZZPs2xu+kw64e2CheTwS6pgmH1DXBgpJfAo=", "LJsE/B9ZOF5PmmdxEQjiLmyHEEzfGmsX9HiXp3ZTiTU=", "VEnlDOQVZn3+NExF7G53geFQZYNf6U5DexkG4vgRlLQ=", "auvWhUrmnBq8g0KEcbAMvjyfrOYhAmiC5+yXjoBsGiw=", "8Cr3zC0dQe124OAQufmKfTZ8lnAYWQuw6AnXuy6DDMQ=", "tbcHjIX6G446NLcoiLw+hjALDmPwWWErWEOvrndCH7Q=", "Bj4reJ88xQpUq0P43RDNLi1sLcLaEeH443F87S4CHoc=", "mAX/zvx1jR0ujLtDApsQpHyxmoDGidClHMOn0BX1aQA=", "u5LKLBPTYgXZg0fBi6/8LuEeNy3EBAxJF0AkkB4Co6E=", "SPUVncwJRVX/n/RICCYqLpAzraqx7S0eMdXRr1RLRgg=", "uEJFtwcGQJMd9kjQhkXb7gl2WD3WMElCc15uDFvFGxs=", "VdOKzpQhJlpXgijzXANf/hNlje1G/N1kUuVnKNskkso=", "mta5fH/gFwxJ/0fT8yGpn3sFCY0G1RY555Iflm0LInM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n107045297\nhgR6aB6kU+T1uo4iUx75tlIhKkYbUyPsHac2yhFgZpE=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiEAqS6BBP1515FNbJUk/993J1ftsTnoVvZ3qFtXGB5WT6cCIGjBPbInr7P6zATImuD6RaTQfWxcPpmcquKCZbAnIseq\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2MWE0MjkxOWUxM2Q1MzlmNzY3M2NmMTFkMWM0MDQzODBlMjhlNTQwNTEwODYwYjlkMjQyMTk2ZTE2NTcwOWM5In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRVJHRUpUU0RXOVhjR0lDbFZKVXdXOFcyeTlHdVRIQnNJUXozTE9pVkU1R0FpQWFINnVTdVBSNmYvbURkeXN0Q1JLZWVreWdrVmZvQ3gyekJGWGVNRUNxNEE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTXdSRU5EUVd4WFowRjNTVUpCWjBsVlJ6SXlPVkpMYUVsV1NFaE9hSElyWWxwV05UVlFPRVl2U21sWmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVxUVhwTlZHdDVUVVJSTVZkb1kwNU5hbFYzVG1wQmVrMVVhM3BOUkZFeFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZJUVdScmF6TkhiVkZUVkV4SVlVRXpjV2R6T0UxMGJ6azNUMU5XWWxab1lVNWllbE1LUmpKbFlYUm5SRWxMU2xWclZVWTVRa1p4ZUN0U1MxWlpZa2hWTlVaUlNraGtkMEUxVkRZM1QyWm9ZVVJaU0dsNVlYRlBRMEZZVVhkblowWjNUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZoUWpCSUNtMUpielk1U1ZSdVZUa3hjbmwxZVVGTFV6Um9jMkpuZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlraFdjbGxZVGpaUlIzaG9ZbTFrYUV4dVFuTk5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVhkWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWprS1FraHpRV1ZSUWpOQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnNlbU01VEZwM1FRcEJRVkZFUVVWbmQxSm5TV2hCUzFaNFJFcHViMjF6VjBwaFdFaHpTMHQxTVRseFZuWm1ZVkJ1ZDBzMVdWRllSMjlKT1ZOTGJpdE9Ta0ZwUlVFclEweHNDalV2VmtSTlV5dFZUVlk0VG1nck9EbEtNbnBqY0dONWNFVm9kelpETkhSWE1VSkRRM1ZFUVhkRFoxbEpTMjlhU1hwcU1FVkJkMDFFWVZGQmQxcG5TWGdLUVVsRGRHNTNWVzlzWTAweFoyczNTa0poYlhaR1RWTjNPVXN4V1Zob1ZHRkZjbWRVVmxSc1Nrc3JjRlo1TjBkdWRVYzVjMFprUWtGdk1XTjFNbXc0U3dwd2QwbDRRVkJoTUhNeVlqWmpielp3VVdaSWVGaGlWRUZFUW5Od05GZFVObGx0YVZjM1FTczVNa3BzZDFrNE4zWkVLemRrVURGeVMzcFhNMDVYVWxwUENrVTFRbTV4VVQwOUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "YaQpGeE9U592c88R0cQEOA4o5UBRCGC50kIZbhZXCck="}, "signature": "MEQCIERGEJTSDW9XcGIClVJUwW8W2y9GuTHBsIQz3LOiVE5GAiAaH6uSuPR6f/mDdystCRKeekygkVfoCx2zBFXeMECq4A=="}} diff --git a/python39.changes b/python39.changes index 71b9a11..7560fe9 100644 --- a/python39.changes +++ b/python39.changes @@ -1,3 +1,44 @@ +------------------------------------------------------------------- +Mon Jun 9 16:14:05 UTC 2025 - Matej Cepl + +- Update to 3.9.23: + - Security + - gh-135034: Fixes multiple issues that allowed tarfile + extraction filters (filter="data" and filter="tar") to be + bypassed using crafted symlinks and hard links. + Addresses CVE-2024-12718 (bsc#1244056), CVE-2025-4138 + (bsc#1244059), CVE-2025-4330 (bsc#1244060), and + CVE-2025-4517 (bsc#1244032). + - gh-133767: Fix use-after-free in the “unicode-escape” + decoder with a non-“strict” error handler (CVE-2025-4516, + bsc#1243273). + - gh-128840: Short-circuit the processing of long IPv6 + addresses early in ipaddress to prevent excessive memory + consumption and a minor denial-of-service. + - gh-80222: Fix bug in the folding of quoted strings + when flattening an email message using a modern email + policy. Previously when a quoted string was folded so + that it spanned more than one line, the surrounding + quotes and internal escapes would be omitted. This could + theoretically be used to spoof header lines using a + carefully constructed quoted string if the resulting + rendered email was transmitted or re-parsed. + - Library + - gh-128840: Fix parsing long IPv6 addresses with embedded + IPv4 address. + - gh-134062: ipaddress: fix collisions in __hash__() for + IPv4Network and IPv6Network objects. + - gh-123409: Fix ipaddress.IPv6Address.reverse_pointer output + according to RFC 3596, §2.5. Patch by Bénédikt Tran. + - bpo-43633: Improve the textual representation of + IPv4-mapped IPv6 addresses (RFC 4291 Sections 2.2, 2.5.5.2) + in ipaddress. Patch by Oleksandr Pavliuk. + - bpo-25264: os.path.realpath() now accepts a strict + keyword-only argument. When set to True, OSError is raised + if a path doesn’t exist or a symlink loop is encountered. +- Remove upstreamed patches: + - CVE-2025-4516-DecodeError-handler.patch + ------------------------------------------------------------------- Thu May 22 13:01:17 UTC 2025 - Matej Cepl diff --git a/python39.spec b/python39.spec index 01e511d..b77a86c 100644 --- a/python39.spec +++ b/python39.spec @@ -99,7 +99,7 @@ %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.23 Release: 0 Summary: Python 3 Interpreter License: Python-2.0 @@ -192,9 +192,6 @@ 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 @@ -466,7 +463,6 @@ other applications. %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 diff --git a/sphinx-802.patch b/sphinx-802.patch index de00f20..6e75210 100644 --- a/sphinx-802.patch +++ b/sphinx-802.patch @@ -1,12 +1,10 @@ --- - Doc/tools/extensions/pyspecific.py | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) + Doc/tools/extensions/pyspecific.py | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 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: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 @@ +--- a/Doc/tools/extensions/pyspecific.py ++++ b/Doc/tools/extensions/pyspecific.py +@@ -28,7 +28,13 @@ try: except ImportError: from sphinx.environment import NoUri from sphinx.locale import _ as sphinx_gettext @@ -21,3 +19,12 @@ Index: Python-3.9.22/Doc/tools/extensions/pyspecific.py from sphinx.util.nodes import split_explicit_title from sphinx.writers.text import TextWriter, TextTranslator from sphinx.writers.latex import LaTeXTranslator +@@ -338,7 +344,7 @@ class PyAbstractMethod(PyMethod): + def expand_version_arg(argument, release): + """Expand "next" to the current version""" + if argument == 'next': +- return translators['sphinx'].gettext('{} (unreleased)').format(release) ++ return sphinx_gettext('{} (unreleased)').format(release) + return argument + +