diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-08-11 18:13:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-11 18:13:46 (GMT) |
commit | 04cc01453db2f0af72a06440831637f8bf512daf (patch) | |
tree | 84854fa4bd5b10588eef404a2c22fe65ad25a244 /Modules/_winapi.c | |
parent | a39f0a350662f1978104ee1136472d784aa6f29c (diff) | |
download | cpython-04cc01453db2f0af72a06440831637f8bf512daf.zip cpython-04cc01453db2f0af72a06440831637f8bf512daf.tar.gz cpython-04cc01453db2f0af72a06440831637f8bf512daf.tar.bz2 |
gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832)
* 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.
Diffstat (limited to 'Modules/_winapi.c')
-rw-r--r-- | Modules/_winapi.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0edb36d..eec3349 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1539,40 +1539,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; |