From 77f551548c888b576707ab2647478de00365a4fd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 27 Jul 2025 13:17:59 +0300 Subject: [PATCH 1/2] Remove optimistic allocation in locale.strxfrm() On modern systems, the result of wcsxfrm() is much larger the size of the input string (from 4+2*n on Windows to 4+5*n on Linux for simple ASCII strings), so optimistic allocation of the buffer of the same size never works. --- Modules/_localemodule.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 41e6d48b1dbd9b..c0b63648676bfd 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -409,33 +409,23 @@ _locale_strxfrm_impl(PyObject *module, PyObject *str) } /* assume no change in size, first */ - n1 = n1 + 1; - buf = PyMem_New(wchar_t, n1); + errno = 0; + n2 = wcsxfrm(NULL, s, 0); + if (errno && errno != ERANGE) { + PyErr_SetFromErrno(PyExc_OSError); + goto exit; + } + buf = PyMem_New(wchar_t, n2+1); if (!buf) { PyErr_NoMemory(); goto exit; } errno = 0; - n2 = wcsxfrm(buf, s, n1); - if (errno && errno != ERANGE) { + n2 = wcsxfrm(buf, s, n2+1); + if (errno) { PyErr_SetFromErrno(PyExc_OSError); goto exit; } - if (n2 >= (size_t)n1) { - /* more space needed */ - wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t)); - if (!new_buf) { - PyErr_NoMemory(); - goto exit; - } - buf = new_buf; - errno = 0; - n2 = wcsxfrm(buf, s, n2+1); - if (errno) { - PyErr_SetFromErrno(PyExc_OSError); - goto exit; - } - } result = PyUnicode_FromWideChar(buf, n2); exit: PyMem_Free(buf); From fbf6e8e31c37f561142d4d7b89f1f242a80c68d4 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 27 Jul 2025 14:14:11 +0300 Subject: [PATCH 2/2] Remove outdated comment. --- Modules/_localemodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index c0b63648676bfd..a4c8dc22f91885 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -408,7 +408,6 @@ _locale_strxfrm_impl(PyObject *module, PyObject *str) goto exit; } - /* assume no change in size, first */ errno = 0; n2 = wcsxfrm(NULL, s, 0); if (errno && errno != ERANGE) { @@ -420,6 +419,7 @@ _locale_strxfrm_impl(PyObject *module, PyObject *str) PyErr_NoMemory(); goto exit; } + errno = 0; n2 = wcsxfrm(buf, s, n2+1); if (errno) {