bpo-42658: Use LCMapStringEx in ntpath.normcase to match OS behaviour for case-folding (GH-93591)

* bpo-42658: Use LCMapStringEx in ntpath.normcase to match OS behaviour for case-folding (GH-32010)

* Use AsWideCharString to avoid memory leaks in deprectated unicode converter

Co-authored-by: AN Long <aisk@users.noreply.github.com>
This commit is contained in:
Steve Dower 2022-06-10 11:14:25 +01:00 committed by GitHub
parent f384a8e477
commit 927b5afee7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 8 deletions

View file

@ -1512,6 +1512,68 @@ _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
}
}
/*[clinic input]
_winapi.LCMapStringEx
locale: unicode
flags: DWORD
src: unicode
[clinic start generated code]*/
static PyObject *
_winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
PyObject *src)
/*[clinic end generated code: output=8ea4c9d85a4a1f23 input=2fa6ebc92591731b]*/
{
if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV |
LCMAP_SORTKEY)) {
return PyErr_Format(PyExc_ValueError, "unsupported flags");
}
wchar_t *locale_ = PyUnicode_AsWideCharString(locale, NULL);
if (!locale_) {
return NULL;
}
wchar_t *src_ = PyUnicode_AsWideCharString(src, NULL);
if (!src_) {
PyMem_Free(locale_);
return NULL;
}
int dest_size = LCMapStringEx(locale_, flags, src_, -1, NULL, 0,
NULL, NULL, 0);
if (dest_size == 0) {
PyMem_Free(locale_);
PyMem_Free(src_);
return PyErr_SetFromWindowsErr(0);
}
wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
if (dest == NULL) {
PyMem_Free(locale_);
PyMem_Free(src_);
return PyErr_NoMemory();
}
int nmapped = LCMapStringEx(locale_, flags, src_, -1, dest, dest_size,
NULL, NULL, 0);
if (nmapped == 0) {
DWORD error = GetLastError();
PyMem_Free(locale_);
PyMem_Free(src_);
PyMem_DEL(dest);
return PyErr_SetFromWindowsErr(error);
}
PyObject *ret = PyUnicode_FromWideChar(dest, dest_size - 1);
PyMem_Free(locale_);
PyMem_Free(src_);
PyMem_DEL(dest);
return ret;
}
/*[clinic input]
_winapi.ReadFile
@ -2023,6 +2085,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_OPENFILEMAPPING_METHODDEF
_WINAPI_OPENPROCESS_METHODDEF
_WINAPI_PEEKNAMEDPIPE_METHODDEF
_WINAPI_LCMAPSTRINGEX_METHODDEF
_WINAPI_READFILE_METHODDEF
_WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
_WINAPI_TERMINATEPROCESS_METHODDEF
@ -2160,6 +2223,22 @@ static int winapi_exec(PyObject *m)
WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
WINAPI_CONSTANT("u", LOCALE_NAME_INVARIANT);
WINAPI_CONSTANT(F_DWORD, LOCALE_NAME_MAX_LENGTH);
WINAPI_CONSTANT("u", LOCALE_NAME_SYSTEM_DEFAULT);
WINAPI_CONSTANT("u", LOCALE_NAME_USER_DEFAULT);
WINAPI_CONSTANT(F_DWORD, LCMAP_FULLWIDTH);
WINAPI_CONSTANT(F_DWORD, LCMAP_HALFWIDTH);
WINAPI_CONSTANT(F_DWORD, LCMAP_HIRAGANA);
WINAPI_CONSTANT(F_DWORD, LCMAP_KATAKANA);
WINAPI_CONSTANT(F_DWORD, LCMAP_LINGUISTIC_CASING);
WINAPI_CONSTANT(F_DWORD, LCMAP_LOWERCASE);
WINAPI_CONSTANT(F_DWORD, LCMAP_SIMPLIFIED_CHINESE);
WINAPI_CONSTANT(F_DWORD, LCMAP_TITLECASE);
WINAPI_CONSTANT(F_DWORD, LCMAP_TRADITIONAL_CHINESE);
WINAPI_CONSTANT(F_DWORD, LCMAP_UPPERCASE);
WINAPI_CONSTANT("i", NULL);
return 0;