]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-106844: Fix issues in _winapi.LCMapStringEx (GH-107832) (GH-107875)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 12 Aug 2023 11:06:56 +0000 (14:06 +0300)
committerGitHub <noreply@github.com>
Sat, 12 Aug 2023 11:06:56 +0000 (14:06 +0300)
* 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)

Lib/test/test_ntpath.py
Misc/NEWS.d/next/Windows/2023-07-18-13-01-26.gh-issue-106844.mci4xO.rst [new file with mode: 0644]
Modules/_winapi.c

index 646e81d1e2fa9be49c83c6d7c304cebaa6f66b0a..75e50d92ed1eb1b07970c4c655cff8fb891d3cdd 100644 (file)
@@ -908,6 +908,7 @@ class PathLikeTests(NtpathTestCase):
         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 (file)
index 0000000..11fca7e
--- /dev/null
@@ -0,0 +1 @@
+Fix integer overflow in :func:`!_winapi.LCMapStringEx` which affects :func:`ntpath.normcase`.
index 5c61d99a837515d817416c561242679ad740cfd4..7fb1f2f561b0f9ae099d8d0ec229bd6b0ebb170b 100644 (file)
@@ -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;