summaryrefslogtreecommitdiffstats
path: root/Modules/_winapi.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-08-11 18:13:46 (GMT)
committerGitHub <noreply@github.com>2023-08-11 18:13:46 (GMT)
commit04cc01453db2f0af72a06440831637f8bf512daf (patch)
tree84854fa4bd5b10588eef404a2c22fe65ad25a244 /Modules/_winapi.c
parenta39f0a350662f1978104ee1136472d784aa6f29c (diff)
downloadcpython-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.c34
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;