diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-08-16 10:10:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-16 10:10:42 (GMT) |
commit | b5176a86bd2587856f88aec3958ad8caef7b11fc (patch) | |
tree | 05d4f4c35fedcef25b71320d992aaca9ff298fe6 /Modules | |
parent | aa9707dda9f8dcbe2ada8d8a7280f0f6a8229c59 (diff) | |
download | cpython-b5176a86bd2587856f88aec3958ad8caef7b11fc.zip cpython-b5176a86bd2587856f88aec3958ad8caef7b11fc.tar.gz cpython-b5176a86bd2587856f88aec3958ad8caef7b11fc.tar.bz2 |
[3.12] gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832) (#107874)
* Strings with length from 2**31-1 to 2**32-2 always caused MemoryError,
it doesn't matter how much memory is available.
* Strings with length exactly 2**32-1 caused OSError.
* Strings longer than 2**32-1 characters were truncated due to integer overflow bug.
* Strings containing the null character were truncated at the first null character.
Now strings longer than 2**31-1 characters caused OverflowError and the null character is allowed..
(cherry picked from commit 04cc01453db2f0af72a06440831637f8bf512daf)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_winapi.c | 34 | ||||
-rw-r--r-- | Modules/clinic/_winapi.c.h | 12 |
2 files changed, 30 insertions, 16 deletions
diff --git a/Modules/_winapi.c b/Modules/_winapi.c index d6d2f4a..7727540 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1538,40 +1538,56 @@ _winapi.LCMapStringEx locale: LPCWSTR flags: DWORD - src: LPCWSTR + src: unicode [clinic start generated code]*/ static PyObject * _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags, - LPCWSTR src) -/*[clinic end generated code: output=cf4713d80e2b47c9 input=9fe26f95d5ab0001]*/ + PyObject *src) +/*[clinic end generated code: output=b90e6b26e028ff0a input=3e3dcd9b8164012f]*/ { if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV | LCMAP_SORTKEY)) { return PyErr_Format(PyExc_ValueError, "unsupported flags"); } - int dest_size = LCMapStringEx(locale, flags, src, -1, NULL, 0, + Py_ssize_t src_size; + wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size); + if (!src_) { + return NULL; + } + if (src_size > INT_MAX) { + PyMem_Free(src_); + PyErr_SetString(PyExc_OverflowError, "input string is too long"); + return NULL; + } + + int dest_size = LCMapStringEx(locale, flags, src_, (int)src_size, NULL, 0, NULL, NULL, 0); - if (dest_size == 0) { - return PyErr_SetFromWindowsErr(0); + if (dest_size <= 0) { + DWORD error = GetLastError(); + PyMem_Free(src_); + return PyErr_SetFromWindowsErr(error); } wchar_t* dest = PyMem_NEW(wchar_t, dest_size); if (dest == NULL) { + PyMem_Free(src_); return PyErr_NoMemory(); } - int nmapped = LCMapStringEx(locale, flags, src, -1, dest, dest_size, + int nmapped = LCMapStringEx(locale, flags, src_, (int)src_size, dest, dest_size, NULL, NULL, 0); - if (nmapped == 0) { + if (nmapped <= 0) { DWORD error = GetLastError(); + PyMem_Free(src_); PyMem_DEL(dest); return PyErr_SetFromWindowsErr(error); } - PyObject *ret = PyUnicode_FromWideChar(dest, dest_size - 1); + PyMem_Free(src_); + PyObject *ret = PyUnicode_FromWideChar(dest, nmapped); PyMem_DEL(dest); return ret; diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index 3767b19..1394a8f 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -885,7 +885,7 @@ PyDoc_STRVAR(_winapi_LCMapStringEx__doc__, static PyObject * _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags, - LPCWSTR src); + PyObject *src); static PyObject * _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -912,16 +912,16 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, static const char * const _keywords[] = {"locale", "flags", "src", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .format = "O&kO&:LCMapStringEx", + .format = "O&kU:LCMapStringEx", .kwtuple = KWTUPLE, }; #undef KWTUPLE LPCWSTR locale = NULL; DWORD flags; - LPCWSTR src = NULL; + PyObject *src; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - _PyUnicode_WideCharString_Converter, &locale, &flags, _PyUnicode_WideCharString_Converter, &src)) { + _PyUnicode_WideCharString_Converter, &locale, &flags, &src)) { goto exit; } return_value = _winapi_LCMapStringEx_impl(module, locale, flags, src); @@ -929,8 +929,6 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: /* Cleanup for locale */ PyMem_Free((void *)locale); - /* Cleanup for src */ - PyMem_Free((void *)src); return return_value; } @@ -1481,4 +1479,4 @@ exit: return return_value; } -/*[clinic end generated code: output=be1343b3759e0c96 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9d43ae4bdbe1126a input=a9049054013a1b77]*/ |