Skip to content

Commit ec254c5

Browse files
[3.11] gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832) (GH-107875)
* 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. Now strings longer than 2**31-1 characters caused OverflowError. (cherry picked from commit 04cc014)
1 parent 4ddfb04 commit ec254c5

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

Lib/test/test_ntpath.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ def test_path_normcase(self):
908908
self._check_function(self.path.normcase)
909909
if sys.platform == 'win32':
910910
self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
911+
self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def')
911912

912913
def test_path_isabs(self):
913914
self._check_function(self.path.isabs)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix integer overflow in :func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`.

Modules/_winapi.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,24 +1571,26 @@ _winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
15711571
if (!locale_) {
15721572
return NULL;
15731573
}
1574-
Py_ssize_t srcLenAsSsize;
1575-
int srcLen;
1576-
wchar_t *src_ = PyUnicode_AsWideCharString(src, &srcLenAsSsize);
1574+
Py_ssize_t src_size;
1575+
wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size);
15771576
if (!src_) {
15781577
PyMem_Free(locale_);
15791578
return NULL;
15801579
}
1581-
srcLen = (int)srcLenAsSsize;
1582-
if (srcLen != srcLenAsSsize) {
1583-
srcLen = -1;
1580+
if (src_size > INT_MAX) {
1581+
PyMem_Free(locale_);
1582+
PyMem_Free(src_);
1583+
PyErr_SetString(PyExc_OverflowError, "input string is too long");
1584+
return NULL;
15841585
}
15851586

1586-
int dest_size = LCMapStringEx(locale_, flags, src_, srcLen, NULL, 0,
1587+
int dest_size = LCMapStringEx(locale_, flags, src_, (int)src_size, NULL, 0,
15871588
NULL, NULL, 0);
1588-
if (dest_size == 0) {
1589+
if (dest_size <= 0) {
1590+
DWORD error = GetLastError();
15891591
PyMem_Free(locale_);
15901592
PyMem_Free(src_);
1591-
return PyErr_SetFromWindowsErr(0);
1593+
return PyErr_SetFromWindowsErr(error);
15921594
}
15931595

15941596
wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
@@ -1598,19 +1600,19 @@ _winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
15981600
return PyErr_NoMemory();
15991601
}
16001602

1601-
int nmapped = LCMapStringEx(locale_, flags, src_, srcLen, dest, dest_size,
1603+
int nmapped = LCMapStringEx(locale_, flags, src_, (int)src_size, dest, dest_size,
16021604
NULL, NULL, 0);
1603-
if (nmapped == 0) {
1605+
if (nmapped <= 0) {
16041606
DWORD error = GetLastError();
16051607
PyMem_Free(locale_);
16061608
PyMem_Free(src_);
16071609
PyMem_DEL(dest);
16081610
return PyErr_SetFromWindowsErr(error);
16091611
}
16101612

1611-
PyObject *ret = PyUnicode_FromWideChar(dest, dest_size);
16121613
PyMem_Free(locale_);
16131614
PyMem_Free(src_);
1615+
PyObject *ret = PyUnicode_FromWideChar(dest, nmapped);
16141616
PyMem_DEL(dest);
16151617

16161618
return ret;

0 commit comments

Comments
 (0)