- Update to 3.10.18:
- 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.
- 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.
- Remove upstreamed patches:
- gh-126572-test_ssl-no-stop-ThreadedEchoServer-OSError.patch
- CVE-2025-4516-DecodeError-handler.patch
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python310?expand=0&rev=182
This commit is contained in:
@@ -1,425 +0,0 @@
|
||||
From 8b528cacbbde60504f6ac62784d04889d285f18b 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.10] 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)
|
||||
|
||||
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/string_parser.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
|
||||
@@ -844,6 +844,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
|
||||
@@ -1181,20 +1181,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")
|
||||
@@ -2408,20 +2420,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
|
||||
@@ -1089,10 +1089,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;
|
||||
@@ -1106,7 +1107,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) {
|
||||
@@ -1181,9 +1183,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--;
|
||||
@@ -1197,21 +1200,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
|
||||
@@ -6432,20 +6432,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) {
|
||||
@@ -6628,9 +6631,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);
|
||||
@@ -6669,22 +6675,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/string_parser.c
|
||||
+++ b/Parser/string_parser.c
|
||||
@@ -114,12 +114,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);
|
||||
@@ -133,14 +136,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;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4c68050f049d1b4ac5aadd0df5f27941c0350d2a9e7ab0907ee5eb5225d9d6b0
|
||||
size 19608144
|
||||
@@ -1 +0,0 @@
|
||||
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzzCCAlSgAwIBAgIUI5tsj9NzdgrO+5YskNyoC+qi8vkwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNDA4MTMyMzU4WhcNMjUwNDA4MTMzMzU4WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAv6UJQmrkdgLDaQZmsfd0+gKL2DB6IBsuTQ7oauCQQ3l9hD+hyV5dIcacEb6/y+cfdsll0A0sDGcfJxqInKdbqOCAXMwggFvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUbIExDLYBM5EaJKSM42GWOQ+p+4EwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGWFZJpOwAABAMASDBGAiEA41BGN2vh87VMWZ04uMz41nJe9XjHclR25kZymgE4EoUCIQDcq1G4PeYggbgsgJRK/wA2oT/9c66Ut00r4FTtzKp8nzAKBggqhkjOPQQDAwNpADBmAjEAiQAaAbnKP6BK0IW3WSeDIxogOIzNlO8A5XBjpD+0gPOJTrdXKlNnpwrIg5IEzVFuAjEAio/NN8hD96Rpy+vU8Gejg6xrGYW7kDhfZfGhDQ7ZCXbG5k/Ue9azE/+dOlZ3zfUe"}, "tlogEntries": [{"logIndex": "193846451", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1744118639", "inclusionPromise": {"signedEntryTimestamp": "MEUCIFxLjN8+W16mUiOJzYXkED4rZG+LGsnmcbCknQ+GXGhuAiEA6ARsL3PI6HN7vz2jY2Ef3lzIUqNXJ3fFN08xH1LdWyM="}, "inclusionProof": {"logIndex": "71942189", "rootHash": "t0jBkeXT4fpLCFcUfGvPMrTn6cGyGgGput6RoghhPSM=", "treeSize": "71942196", "hashes": ["+smebvByxaA1Ma1XWJKpZpS5bT3MTjkWgbE8QsnP7iM=", "KTftkiWp8T5wzTX2uRjjb9cOPgzQYm12kVViECWEcF0=", "eT+T8QsO14DNUNRvdA8DN3nkWATbZNBttN7hMwLhDRs=", "/cpMfdkyRFEgNofmHSovLaOnUrMdzl1GlnYJQ83emgU=", "yYb3Qj3G9bz700MryqKxLQkwbVYczRq5u/0VXtsPV2Y=", "yOOivaVwYhqQJnOzhyJxD03KD1BxbsqOm30ZuiDpf6M=", "Pz/WMQQ6nBmkX4L+rVteCufItRYXtXpzlTBnxzaVr8E=", "cuMOBvg9q/3wCGMfCdrFlvXHmcIXecnD3xPny77dAWw=", "wz8AVqzGBjixNiXtnCb16MFP7zOW54eYx/zJ/1Jey/E=", "K26LG80DXyb+bC58c4Nw00WigG52v0PCsZGY3ExGsts=", "WEm5OgPzJpYROv+4CcrieexCYyQKrLUH3hbxmcQQ+DM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n71942196\nt0jBkeXT4fpLCFcUfGvPMrTn6cGyGgGput6RoghhPSM=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEAp55/To5P2lvHGyciQR/vCYaZ5R5972Hzrj7ZIYnqDk0CIQCEZbKDx3oGXIV5S0tYiR+MrDRDDV5ly/Dep8URvrU4xw==\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI0YzY4MDUwZjA0OWQxYjRhYzVhYWRkMGRmNWYyNzk0MWMwMzUwZDJhOWU3YWIwOTA3ZWU1ZWI1MjI1ZDlkNmIwIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUR4QUFKRUhOaDY3NzJjQUNWNlFtWEVZK3k5UHA1Z2twUlpuZTZmRFFOazRBSWdaMDJVN1BvNFlYNDRZRTFwdHQ3RHh6MDlCSE5XLzRucjhmdzNVUHdkUStNPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZla05EUVd4VFowRjNTVUpCWjBsVlNUVjBjMm81VG5wa1ozSlBLelZaYzJ0T2VXOURLM0ZwT0hacmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVFUVRSTlZFMTVUWHBWTkZkb1kwNU5hbFYzVGtSQk5FMVVUWHBOZWxVMFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZCZGpaVlNsRnRjbXRrWjB4RVlWRmFiWE5tWkRBclowdE1Na1JDTmtsQ2MzVlVVVGNLYjJGMVExRlJNMnc1YUVRcmFIbFdOV1JKWTJGalJXSTJMM2tyWTJaa2MyeHNNRUV3YzBSSFkyWktlSEZKYmt0a1luRlBRMEZZVFhkblowWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZpU1VWNENrUk1XVUpOTlVWaFNrdFRUVFF5UjFkUFVTdHdLelJGZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVVS1pYZENOVUZJWTBFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxZEdXa3B3VDNkQlFRcENRVTFCVTBSQ1IwRnBSVUUwTVVKSFRqSjJhRGczVmsxWFdqQTBkVTE2TkRGdVNtVTVXR3BJWTJ4U01qVnJXbmx0WjBVMFJXOVZRMGxSUkdOeE1VYzBDbEJsV1dkblltZHpaMHBTU3k5M1FUSnZWQzg1WXpZMlZYUXdNSEkwUmxSMGVrdHdPRzU2UVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV3UVVSQ2JVRnFSVUVLYVZGQllVRmlia3RRTmtKTE1FbFhNMWRUWlVSSmVHOW5UMGw2VG14UE9FRTFXRUpxY0VRck1HZFFUMHBVY21SWVMyeE9ibkIzY2tsbk5VbEZlbFpHZFFwQmFrVkJhVzh2VGs0NGFFUTVObEp3ZVN0MlZUaEhaV3BuTm5oeVIxbFhOMnRFYUdaYVprZG9SRkUzV2tOWVlrYzFheTlWWlRsaGVrVXZLMlJQYkZvekNucG1WV1VLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "TGgFDwSdG0rFqt0N9fJ5QcA1DSqeerCQfuXrUiXZ1rA="}, "signature": "MEUCIQDxAAJEHNh6772cACV6QmXEY+y9Pp5gkpRZne6fDQNk4AIgZ02U7Po4YX44YE1ptt7Dxz09BHNW/4nr8fw3UPwdQ+M="}}
|
||||
3
Python-3.10.18.tar.xz
Normal file
3
Python-3.10.18.tar.xz
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ae665bc678abd9ab6a6e1573d2481625a53719bc517e9a634ed2b9fefae3817f
|
||||
size 19619316
|
||||
1
Python-3.10.18.tar.xz.sigstore
Normal file
1
Python-3.10.18.tar.xz.sigstore
Normal file
File diff suppressed because one or more lines are too long
@@ -3,11 +3,9 @@
|
||||
Misc/NEWS | 2 +-
|
||||
2 files changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
Index: Python-3.10.17/Doc/using/configure.rst
|
||||
===================================================================
|
||||
--- Python-3.10.17.orig/Doc/using/configure.rst 2025-04-08 14:10:59.000000000 +0200
|
||||
+++ Python-3.10.17/Doc/using/configure.rst 2025-04-11 10:07:56.572228089 +0200
|
||||
@@ -42,7 +42,6 @@
|
||||
--- a/Doc/using/configure.rst
|
||||
+++ b/Doc/using/configure.rst
|
||||
@@ -42,7 +42,6 @@ General Options
|
||||
|
||||
See :data:`sys.int_info.bits_per_digit <sys.int_info>`.
|
||||
|
||||
@@ -15,7 +13,7 @@ Index: Python-3.10.17/Doc/using/configure.rst
|
||||
.. cmdoption:: --with-cxx-main=COMPILER
|
||||
|
||||
Compile the Python ``main()`` function and link Python executable with C++
|
||||
@@ -473,13 +472,11 @@
|
||||
@@ -473,13 +472,11 @@ macOS Options
|
||||
|
||||
See ``Mac/README.rst``.
|
||||
|
||||
@@ -29,11 +27,9 @@ Index: Python-3.10.17/Doc/using/configure.rst
|
||||
.. cmdoption:: --enable-framework=INSTALLDIR
|
||||
|
||||
Create a Python.framework rather than a traditional Unix install. Optional
|
||||
Index: Python-3.10.17/Misc/NEWS
|
||||
===================================================================
|
||||
--- Python-3.10.17.orig/Misc/NEWS 2025-04-08 14:10:59.000000000 +0200
|
||||
+++ Python-3.10.17/Misc/NEWS 2025-04-11 10:07:56.576558000 +0200
|
||||
@@ -3903,7 +3903,7 @@
|
||||
--- a/Misc/NEWS
|
||||
+++ b/Misc/NEWS
|
||||
@@ -3942,7 +3942,7 @@ C API
|
||||
-----
|
||||
|
||||
- bpo-43795: The list in :ref:`stable-abi-list` now shows the public name
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
From 3d390148c05a7ea2d401c4633e7d4db75ebf97d9 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Viktorin <encukou@gmail.com>
|
||||
Date: Thu, 7 Nov 2024 11:07:02 +0100
|
||||
Subject: [PATCH] gh-126500: test_ssl: Don't stop ThreadedEchoServer on OSError
|
||||
in ConnectionHandler; rely on __exit__ (GH-126503)
|
||||
|
||||
If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`),
|
||||
the ConnectionHandler shuts down the entire ThreadedEchoServer,
|
||||
preventing further connections.
|
||||
It also does that for `EPROTOTYPE` in `wrap_conn`.
|
||||
|
||||
As far as I can see, this is done to avoid the server thread getting stuck,
|
||||
forgotten, in its accept loop. However, since 2011 (5b95eb90a7167285b6544b50865227c584943c9a)
|
||||
the server is used as a context manager, and its `__exit__` does `stop()` and `join()`.
|
||||
(I'm not sure if we *always* used `with` since that commit, but currently we do.)
|
||||
|
||||
Make sure that the context manager *is* used, and remove the `server.stop()`
|
||||
calls from ConnectionHandler.
|
||||
(cherry picked from commit c9cda1608edf7664c10f4f467e24591062c2fe62)
|
||||
|
||||
Co-authored-by: Petr Viktorin <encukou@gmail.com>
|
||||
---
|
||||
Lib/test/test_ssl.py | 17 ++++++++++++-----
|
||||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/Lib/test/test_ssl.py
|
||||
+++ b/Lib/test/test_ssl.py
|
||||
@@ -2488,7 +2488,6 @@ class ThreadedEchoServer(threading.Threa
|
||||
# See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
|
||||
if e.errno != errno.EPROTOTYPE and sys.platform != "darwin":
|
||||
self.running = False
|
||||
- self.server.stop()
|
||||
self.close()
|
||||
return False
|
||||
else:
|
||||
@@ -2623,10 +2622,6 @@ class ThreadedEchoServer(threading.Threa
|
||||
self.close()
|
||||
self.running = False
|
||||
|
||||
- # normally, we'd just stop here, but for the test
|
||||
- # harness, we want to stop the server
|
||||
- self.server.stop()
|
||||
-
|
||||
def __init__(self, certificate=None, ssl_version=None,
|
||||
certreqs=None, cacerts=None,
|
||||
chatty=True, connectionchatty=False, starttls_server=False,
|
||||
@@ -2660,21 +2655,33 @@ class ThreadedEchoServer(threading.Threa
|
||||
self.conn_errors = []
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
+ self._in_context = False
|
||||
|
||||
def __enter__(self):
|
||||
+ if self._in_context:
|
||||
+ raise ValueError('Re-entering ThreadedEchoServer context')
|
||||
+ self._in_context = True
|
||||
self.start(threading.Event())
|
||||
self.flag.wait()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
+ assert self._in_context
|
||||
+ self._in_context = False
|
||||
self.stop()
|
||||
self.join()
|
||||
|
||||
def start(self, flag=None):
|
||||
+ if not self._in_context:
|
||||
+ raise ValueError(
|
||||
+ 'ThreadedEchoServer must be used as a context manager')
|
||||
self.flag = flag
|
||||
threading.Thread.start(self)
|
||||
|
||||
def run(self):
|
||||
+ if not self._in_context:
|
||||
+ raise ValueError(
|
||||
+ 'ThreadedEchoServer must be used as a context manager')
|
||||
self.sock.settimeout(1.0)
|
||||
self.sock.listen(5)
|
||||
self.active = True
|
||||
@@ -1,3 +1,34 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Jun 9 16:53:24 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||
|
||||
- Update to 3.10.18:
|
||||
- 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.
|
||||
- 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.
|
||||
- Remove upstreamed patches:
|
||||
- gh-126572-test_ssl-no-stop-ThreadedEchoServer-OSError.patch
|
||||
- CVE-2025-4516-DecodeError-handler.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu May 22 13:01:17 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ Obsoletes: python39%{?1:-%{1}}
|
||||
# _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.10.17
|
||||
Version: 3.10.18
|
||||
Release: 0
|
||||
Summary: Python 3 Interpreter
|
||||
License: Python-2.0
|
||||
@@ -202,12 +202,6 @@ Patch27: gh120226-fix-sendfile-test-kernel-610.patch
|
||||
# PATCH-FIX-UPSTREAM sphinx-802.patch mcepl@suse.com
|
||||
# status_iterator method moved between the Sphinx versions
|
||||
Patch28: sphinx-802.patch
|
||||
# PATCH-FIX-UPSTREAM gh-126572-test_ssl-no-stop-ThreadedEchoServer-OSError.patch bsc#1241067 mcepl@suse.com
|
||||
# don't stop ThreadedEchoServer on OSError, makes test_ssl fail with OpenSSL 3.5
|
||||
Patch29: gh-126572-test_ssl-no-stop-ThreadedEchoServer-OSError.patch
|
||||
# PATCH-FIX-UPSTREAM CVE-2025-4516-DecodeError-handler.patch bsc#1243273 mcepl@suse.com
|
||||
# this patch makes things totally awesome
|
||||
Patch30: CVE-2025-4516-DecodeError-handler.patch
|
||||
BuildRequires: autoconf-archive
|
||||
BuildRequires: automake
|
||||
BuildRequires: fdupes
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
Doc/tools/extensions/pyspecific.py | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: Python-3.10.17/Doc/tools/extensions/pyspecific.py
|
||||
===================================================================
|
||||
--- Python-3.10.17.orig/Doc/tools/extensions/pyspecific.py 2025-04-11 10:08:04.200327546 +0200
|
||||
+++ Python-3.10.17/Doc/tools/extensions/pyspecific.py 2025-04-11 10:08:21.185064035 +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
|
||||
|
||||
Reference in New Issue
Block a user