diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 51ba423a0f1c92..3d4fffbb8e794a 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1692,6 +1692,13 @@ def test_run_with_pathlike_path_and_arguments(self): res = subprocess.run(args) self.assertEqual(res.returncode, 57) + @unittest.skipUnless(mswindows, "Maybe test trigger a leak on Ubuntu") + def test_run_with_an_empty_env(self): + # gh-105436: fix subprocess.run(..., env={}) broken on Windows + args = [sys.executable, "-c", 'import sys; sys.exit(57)'] + res = subprocess.run(args, env={}) + self.assertEqual(res.returncode, 57) + def test_capture_output(self): cp = self.run_python(("import sys;" "sys.stdout.write('BDFL'); " diff --git a/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst b/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst new file mode 100644 index 00000000000000..1e3f298096cdd6 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-06-08-11-30-17.gh-issue-105436.1qlDxw.rst @@ -0,0 +1,2 @@ +Ensure that an empty environment block is terminated by two null characters, +as is required by Windows. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index bbc9facd227c9e..d6d2f4a6a9b103 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -796,6 +796,17 @@ getenvironment(PyObject* environment) } envsize = PyList_GET_SIZE(keys); + + if (envsize == 0) { + // A environment block must be terminated by two null characters -- + // one for the last string and one for the block. + buffer = PyMem_Calloc(2, sizeof(wchar_t)); + if (!buffer) { + PyErr_NoMemory(); + } + goto cleanup; + } + if (PyList_GET_SIZE(values) != envsize) { PyErr_SetString(PyExc_RuntimeError, "environment changed size during iteration"); @@ -869,7 +880,8 @@ getenvironment(PyObject* environment) *p++ = L'\0'; assert(p == end); - error: +cleanup: +error: Py_XDECREF(keys); Py_XDECREF(values); return buffer;