[Python-checkins] [3.11] gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832) (GH-107875)
serhiy-storchaka
webhook-mailer at python.org
Sat Aug 12 07:07:00 EDT 2023
https://github.com/python/cpython/commit/ec254c5dfa8c99f1ec061b252d155386e93f19ef
commit: ec254c5dfa8c99f1ec061b252d155386e93f19ef
branch: 3.11
author: Serhiy Storchaka <storchaka at gmail.com>
committer: serhiy-storchaka <storchaka at gmail.com>
date: 2023-08-12T14:06:56+03:00
summary:
[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 04cc01453db2f0af72a06440831637f8bf512daf)
files:
A Misc/NEWS.d/next/Windows/2023-07-18-13-01-26.gh-issue-106844.mci4xO.rst
M Lib/test/test_ntpath.py
M Modules/_winapi.c
diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py
index 646e81d1e2fa9..75e50d92ed1eb 100644
--- a/Lib/test/test_ntpath.py
+++ b/Lib/test/test_ntpath.py
@@ -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)
diff --git a/Misc/NEWS.d/next/Windows/2023-07-18-13-01-26.gh-issue-106844.mci4xO.rst b/Misc/NEWS.d/next/Windows/2023-07-18-13-01-26.gh-issue-106844.mci4xO.rst
new file mode 100644
index 0000000000000..11fca7e0452f4
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2023-07-18-13-01-26.gh-issue-106844.mci4xO.rst
@@ -0,0 +1 @@
+Fix integer overflow in :func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`.
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 5c61d99a83751..7fb1f2f561b0f 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -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);
@@ -1598,9 +1600,9 @@ _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_);
@@ -1608,9 +1610,9 @@ _winapi_LCMapStringEx_impl(PyObject *module, PyObject *locale, DWORD flags,
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;
More information about the Python-checkins
mailing list