Skip to content

Commit dff8b2f

Browse files
committed
pythongh-106844: Fix null-bytes handling in LCMapStringEx in _winapi
1 parent 4cb0b9c commit dff8b2f

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed

Lib/test/test_ntpath.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ def test_path_normcase(self):
10361036
self._check_function(self.path.normcase)
10371037
if sys.platform == 'win32':
10381038
self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
1039+
self.assertEqual(ntpath.normcase('abc\x00def'), 'abcdef')
10391040

10401041
def test_path_isabs(self):
10411042
self._check_function(self.path.isabs)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix null-bytes handling in ``LCMapStringEx`` which affects
2+
:func:`ntpath.normcase`.

Modules/_winapi.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,42 +1537,66 @@ _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
15371537
/*[clinic input]
15381538
_winapi.LCMapStringEx
15391539
1540-
locale: LPCWSTR
1540+
locale: unicode
15411541
flags: DWORD
1542-
src: LPCWSTR
1542+
src: unicode
15431543
15441544
[clinic start generated code]*/
15451545

15461546
static PyObject *
1547-
_winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
1548-
LPCWSTR src)
1549-
/*[clinic end generated code: output=cf4713d80e2b47c9 input=9fe26f95d5ab0001]*/
1547+
_winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
1548+
PyObject *src)
1549+
/*[clinic end generated code: output=8ea4c9d85a4a1f23 input=2fa6ebc92591731b]*/
15501550
{
15511551
if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV |
15521552
LCMAP_SORTKEY)) {
15531553
return PyErr_Format(PyExc_ValueError, "unsupported flags");
15541554
}
15551555

1556-
int dest_size = LCMapStringEx(locale, flags, src, -1, NULL, 0,
1556+
wchar_t *locale_ = PyUnicode_AsWideCharString(locale, NULL);
1557+
if (!locale_) {
1558+
return NULL;
1559+
}
1560+
Py_ssize_t srcLenAsSsize;
1561+
int srcLen;
1562+
wchar_t *src_ = PyUnicode_AsWideCharString(src, &srcLenAsSsize);
1563+
if (!src_) {
1564+
PyMem_Free(locale_);
1565+
return NULL;
1566+
}
1567+
srcLen = (int)srcLenAsSsize;
1568+
if (srcLen != srcLenAsSsize) {
1569+
srcLen = -1;
1570+
}
1571+
1572+
int dest_size = LCMapStringEx(locale_, flags, src_, srcLen, NULL, 0,
15571573
NULL, NULL, 0);
15581574
if (dest_size == 0) {
1575+
PyMem_Free(locale_);
1576+
PyMem_Free(src_);
15591577
return PyErr_SetFromWindowsErr(0);
15601578
}
15611579

15621580
wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
15631581
if (dest == NULL) {
1582+
PyMem_Free(locale_);
1583+
PyMem_Free(src_);
15641584
return PyErr_NoMemory();
15651585
}
15661586

1567-
int nmapped = LCMapStringEx(locale, flags, src, -1, dest, dest_size,
1587+
int nmapped = LCMapStringEx(locale_, flags, src_, srcLen, dest, dest_size,
15681588
NULL, NULL, 0);
15691589
if (nmapped == 0) {
15701590
DWORD error = GetLastError();
1591+
PyMem_Free(locale_);
1592+
PyMem_Free(src_);
15711593
PyMem_DEL(dest);
15721594
return PyErr_SetFromWindowsErr(error);
15731595
}
15741596

1575-
PyObject *ret = PyUnicode_FromWideChar(dest, dest_size - 1);
1597+
PyObject *ret = PyUnicode_FromWideChar(dest, dest_size);
1598+
PyMem_Free(locale_);
1599+
PyMem_Free(src_);
15761600
PyMem_DEL(dest);
15771601

15781602
return ret;

Modules/clinic/_winapi.c.h

Lines changed: 7 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)