Skip to content

Commit

Permalink
[3.11] gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832) (GH…
Browse files Browse the repository at this point in the history
…-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)
  • Loading branch information
serhiy-storchaka committed Aug 12, 2023
1 parent 4ddfb04 commit ec254c5
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 12 deletions.
1 change: 1 addition & 0 deletions Lib/test/test_ntpath.py
Expand Up @@ -908,6 +908,7 @@ def test_path_normcase(self):
self._check_function(self.path.normcase)
if sys.platform == 'win32':
self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def')

def test_path_isabs(self):
self._check_function(self.path.isabs)
Expand Down
@@ -0,0 +1 @@
Fix integer overflow in :func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`.
26 changes: 14 additions & 12 deletions Modules/_winapi.c
Expand Up @@ -1571,24 +1571,26 @@ _winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
if (!locale_) {
return NULL;
}
Py_ssize_t srcLenAsSsize;
int srcLen;
wchar_t *src_ = PyUnicode_AsWideCharString(src, &srcLenAsSsize);
Py_ssize_t src_size;
wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size);
if (!src_) {
PyMem_Free(locale_);
return NULL;
}
srcLen = (int)srcLenAsSsize;
if (srcLen != srcLenAsSsize) {
srcLen = -1;
if (src_size > INT_MAX) {
PyMem_Free(locale_);
PyMem_Free(src_);
PyErr_SetString(PyExc_OverflowError, "input string is too long");
return NULL;
}

int dest_size = LCMapStringEx(locale_, flags, src_, srcLen, NULL, 0,
int dest_size = LCMapStringEx(locale_, flags, src_, (int)src_size, NULL, 0,
NULL, NULL, 0);
if (dest_size == 0) {
if (dest_size <= 0) {
DWORD error = GetLastError();
PyMem_Free(locale_);
PyMem_Free(src_);
return PyErr_SetFromWindowsErr(0);
return PyErr_SetFromWindowsErr(error);
}

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

int nmapped = LCMapStringEx(locale_, flags, src_, srcLen, 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(locale_);
PyMem_Free(src_);
PyMem_DEL(dest);
return PyErr_SetFromWindowsErr(error);
}

PyObject *ret = PyUnicode_FromWideChar(dest, dest_size);
PyMem_Free(locale_);
PyMem_Free(src_);
PyObject *ret = PyUnicode_FromWideChar(dest, nmapped);
PyMem_DEL(dest);

return ret;
Expand Down

0 comments on commit ec254c5

Please sign in to comment.