mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
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.
This commit is contained in:
parent
a39f0a3506
commit
04cc01453d
4 changed files with 32 additions and 16 deletions
|
@ -1036,6 +1036,7 @@ class PathLikeTests(NtpathTestCase):
|
||||||
self._check_function(self.path.normcase)
|
self._check_function(self.path.normcase)
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
|
self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
|
||||||
|
self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def')
|
||||||
|
|
||||||
def test_path_isabs(self):
|
def test_path_isabs(self):
|
||||||
self._check_function(self.path.isabs)
|
self._check_function(self.path.isabs)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix integer overflow and truncating by the null character in :func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`.
|
|
@ -1539,40 +1539,56 @@ _winapi.LCMapStringEx
|
||||||
|
|
||||||
locale: LPCWSTR
|
locale: LPCWSTR
|
||||||
flags: DWORD
|
flags: DWORD
|
||||||
src: LPCWSTR
|
src: unicode
|
||||||
|
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
|
_winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
|
||||||
LPCWSTR src)
|
PyObject *src)
|
||||||
/*[clinic end generated code: output=cf4713d80e2b47c9 input=9fe26f95d5ab0001]*/
|
/*[clinic end generated code: output=b90e6b26e028ff0a input=3e3dcd9b8164012f]*/
|
||||||
{
|
{
|
||||||
if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV |
|
if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV |
|
||||||
LCMAP_SORTKEY)) {
|
LCMAP_SORTKEY)) {
|
||||||
return PyErr_Format(PyExc_ValueError, "unsupported flags");
|
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);
|
NULL, NULL, 0);
|
||||||
if (dest_size == 0) {
|
if (dest_size <= 0) {
|
||||||
return PyErr_SetFromWindowsErr(0);
|
DWORD error = GetLastError();
|
||||||
|
PyMem_Free(src_);
|
||||||
|
return PyErr_SetFromWindowsErr(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
|
wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
|
||||||
if (dest == NULL) {
|
if (dest == NULL) {
|
||||||
|
PyMem_Free(src_);
|
||||||
return PyErr_NoMemory();
|
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);
|
NULL, NULL, 0);
|
||||||
if (nmapped == 0) {
|
if (nmapped <= 0) {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
|
PyMem_Free(src_);
|
||||||
PyMem_DEL(dest);
|
PyMem_DEL(dest);
|
||||||
return PyErr_SetFromWindowsErr(error);
|
return PyErr_SetFromWindowsErr(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *ret = PyUnicode_FromWideChar(dest, dest_size - 1);
|
PyMem_Free(src_);
|
||||||
|
PyObject *ret = PyUnicode_FromWideChar(dest, nmapped);
|
||||||
PyMem_DEL(dest);
|
PyMem_DEL(dest);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
12
Modules/clinic/_winapi.c.h
generated
12
Modules/clinic/_winapi.c.h
generated
|
@ -884,7 +884,7 @@ PyDoc_STRVAR(_winapi_LCMapStringEx__doc__,
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
|
_winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
|
||||||
LPCWSTR src);
|
PyObject *src);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
@ -911,16 +911,16 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
|
||||||
static const char * const _keywords[] = {"locale", "flags", "src", NULL};
|
static const char * const _keywords[] = {"locale", "flags", "src", NULL};
|
||||||
static _PyArg_Parser _parser = {
|
static _PyArg_Parser _parser = {
|
||||||
.keywords = _keywords,
|
.keywords = _keywords,
|
||||||
.format = "O&kO&:LCMapStringEx",
|
.format = "O&kU:LCMapStringEx",
|
||||||
.kwtuple = KWTUPLE,
|
.kwtuple = KWTUPLE,
|
||||||
};
|
};
|
||||||
#undef KWTUPLE
|
#undef KWTUPLE
|
||||||
LPCWSTR locale = NULL;
|
LPCWSTR locale = NULL;
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
LPCWSTR src = NULL;
|
PyObject *src;
|
||||||
|
|
||||||
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
|
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
|
||||||
_PyUnicode_WideCharString_Converter, &locale, &flags, _PyUnicode_WideCharString_Converter, &src)) {
|
_PyUnicode_WideCharString_Converter, &locale, &flags, &src)) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
return_value = _winapi_LCMapStringEx_impl(module, locale, flags, src);
|
return_value = _winapi_LCMapStringEx_impl(module, locale, flags, src);
|
||||||
|
@ -928,8 +928,6 @@ _winapi_LCMapStringEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
|
||||||
exit:
|
exit:
|
||||||
/* Cleanup for locale */
|
/* Cleanup for locale */
|
||||||
PyMem_Free((void *)locale);
|
PyMem_Free((void *)locale);
|
||||||
/* Cleanup for src */
|
|
||||||
PyMem_Free((void *)src);
|
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
@ -1480,4 +1478,4 @@ exit:
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=f32fe6ecdbffd74d input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=ff91ab5cae8961dd input=a9049054013a1b77]*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue