From aed39b7596186c13d77c0eda18b75e230d362143 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 14 Mar 2023 21:13:37 +0800 Subject: [PATCH 01/58] gh-87868: correctly sort and remove duplicates in getenvironment() --- Lib/test/test_subprocess.py | 11 +++ ...3-03-15-23-53-45.gh-issue-87868.4C36oQ.rst | 2 + Modules/_winapi.c | 76 +++++++++++++++++-- 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 3880125807f235..2d8cad5e642da2 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -783,6 +783,17 @@ def test_env(self): stdout, stderr = p.communicate() self.assertEqual(stdout, b"orange") + @unittest.skipUnless(sys.platform == "win32", "Windows only issue") + def test_win32_duplicate_envs(self): + newenv = os.environ.copy() + newenv["fruit"] = "lemon" + newenv["FRUIT"] = "orange" + with subprocess.Popen(["CMD", "/c", "SET", "fruit"], + stdout=subprocess.PIPE, + env=newenv) as p: + stdout, stderr = p.communicate() + self.assertEqual(stdout, b"fruit=lemon\r\n") + # Windows requires at least the SYSTEMROOT environment variable to start # Python @unittest.skipIf(sys.platform == 'win32', diff --git a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst new file mode 100644 index 00000000000000..8f8d0c4b625711 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst @@ -0,0 +1,2 @@ +Correctly sort and remove duplicates environment variables in +``_winapi.CreateProcess``. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 83cde7501176b6..bcc1d40b4d1e2d 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -772,23 +772,88 @@ gethandle(PyObject* obj, const char* name) return ret; } +static PyObject* sortenvironmentkey(PyObject *module, PyObject *item) { + Py_ssize_t n; + wchar_t* s = PyUnicode_AsWideCharString(item, &n); + if (s == NULL) { + return NULL; + } + return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, s); +} + +static PyMethodDef sortenvironmentkey_def = { + "sortenvironmentkey", + _PyCFunction_CAST(sortenvironmentkey), + METH_O, + "" +}; + +static PyObject * +normalize_environment(PyObject* environment) { + PyObject *result, *keys, *keyfunc, *sort, *args, *kwargs; + + keys = PyMapping_Keys(environment); + if (keys == NULL) { + return NULL; + } + + keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); + sort = PyObject_GetAttrString(keys, "sort"); + args = PyTuple_New(0); + kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "key", keyfunc); + if (PyObject_Call(sort, args, kwargs) == NULL) { + goto error; + } + + result = PyDict_New(); + + for (int i = 0; i Date: Fri, 17 Mar 2023 23:33:02 +0800 Subject: [PATCH 02/58] check null in normalize_environment --- Lib/test/test_subprocess.py | 1 + ...3-03-15-23-53-45.gh-issue-87868.4C36oQ.rst | 2 +- Modules/_winapi.c | 60 +++++++++++-------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 2d8cad5e642da2..96ac235e480910 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -788,6 +788,7 @@ def test_win32_duplicate_envs(self): newenv = os.environ.copy() newenv["fruit"] = "lemon" newenv["FRUIT"] = "orange" + newenv["frUit"] = "banana" with subprocess.Popen(["CMD", "/c", "SET", "fruit"], stdout=subprocess.PIPE, env=newenv) as p: diff --git a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst index 8f8d0c4b625711..7206986bf1094f 100644 --- a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst +++ b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst @@ -1,2 +1,2 @@ -Correctly sort and remove duplicates environment variables in +Correctly sort and remove duplicate environment variables in ``_winapi.CreateProcess``. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index bcc1d40b4d1e2d..5770e365601bc1 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -808,18 +808,46 @@ normalize_environment(PyObject* environment) { result = PyDict_New(); - for (int i = 0; i 1); if (totalsize > PY_SSIZE_T_MAX - size) { From c43abb213376465b47986bd99cdeb9d80b98424e Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 20 Aug 2023 16:17:57 +0800 Subject: [PATCH 03/58] Update Modules/_winapi.c Co-authored-by: Pieter Eendebak --- Modules/_winapi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 5770e365601bc1..bd961c90248a47 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -800,7 +800,6 @@ normalize_environment(PyObject* environment) { keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); sort = PyObject_GetAttrString(keys, "sort"); args = PyTuple_New(0); - kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "key", keyfunc); if (PyObject_Call(sort, args, kwargs) == NULL) { goto error; From 3f6319a1c106a878761675cd4fe5c1ac0c922fbc Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 20 Aug 2023 16:18:05 +0800 Subject: [PATCH 04/58] Update Modules/_winapi.c Co-authored-by: Pieter Eendebak --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index bd961c90248a47..aacf8558aa2be2 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -801,7 +801,7 @@ normalize_environment(PyObject* environment) { sort = PyObject_GetAttrString(keys, "sort"); args = PyTuple_New(0); PyDict_SetItemString(kwargs, "key", keyfunc); - if (PyObject_Call(sort, args, kwargs) == NULL) { + if (PyObject_Call(sort, args, NULL) == NULL) { goto error; } From 8ef3b9c65fe592e468dcf67820acd900b5faa5ca Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 20 Aug 2023 16:22:03 +0800 Subject: [PATCH 05/58] Update Lib/test/test_subprocess.py Co-authored-by: Pieter Eendebak --- Lib/test/test_subprocess.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 96ac235e480910..479dc8a40bf5bb 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -786,6 +786,7 @@ def test_env(self): @unittest.skipUnless(sys.platform == "win32", "Windows only issue") def test_win32_duplicate_envs(self): newenv = os.environ.copy() + newenv["fRUit"] = "cherry" newenv["fruit"] = "lemon" newenv["FRUIT"] = "orange" newenv["frUit"] = "banana" From ca1320598b58b3efb0822a5582cf3b31bdeae71f Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 20 Aug 2023 17:48:07 +0800 Subject: [PATCH 06/58] Adapt latest changes from main branch --- Modules/_winapi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index a23155c996c147..6ce97cb2703cef 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -775,12 +775,7 @@ gethandle(PyObject* obj, const char* name) } static PyObject* sortenvironmentkey(PyObject *module, PyObject *item) { - Py_ssize_t n; - wchar_t* s = PyUnicode_AsWideCharString(item, &n); - if (s == NULL) { - return NULL; - } - return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, s); + return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, item); } static PyMethodDef sortenvironmentkey_def = { @@ -802,6 +797,7 @@ normalize_environment(PyObject* environment) { keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); sort = PyObject_GetAttrString(keys, "sort"); args = PyTuple_New(0); + kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "key", keyfunc); if (PyObject_Call(sort, args, NULL) == NULL) { goto error; From f7270040057b166822d779c3dee85a62ce8ec73d Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 20 Aug 2023 20:01:43 +0800 Subject: [PATCH 07/58] Fix test case --- Lib/test/test_subprocess.py | 2 +- Modules/_winapi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index ec03d4af38355d..b9b8a857148711 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -796,7 +796,7 @@ def test_win32_duplicate_envs(self): stdout=subprocess.PIPE, env=newenv) as p: stdout, stderr = p.communicate() - self.assertEqual(stdout, b"fruit=lemon\r\n") + self.assertEqual(stdout, b"fRUit=cherry\r\n") # Windows requires at least the SYSTEMROOT environment variable to start # Python diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 6ce97cb2703cef..df2786ec73f503 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -799,7 +799,7 @@ normalize_environment(PyObject* environment) { args = PyTuple_New(0); kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "key", keyfunc); - if (PyObject_Call(sort, args, NULL) == NULL) { + if (PyObject_Call(sort, args, kwargs) == NULL) { goto error; } From 6b9e8737ed05e5da5207ef6760d9731e2ecf626c Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 3 Sep 2023 17:25:40 +0800 Subject: [PATCH 08/58] update for review comments --- Modules/_winapi.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index df2786ec73f503..18801306173309 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -804,6 +804,7 @@ normalize_environment(PyObject* environment) { } result = PyDict_New(); + wchar_t *prev_key_string = NULL; for (int i=0; i Date: Sun, 3 Sep 2023 18:39:33 +0800 Subject: [PATCH 09/58] add win32 related env validation tests --- Lib/test/test_subprocess.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index b9b8a857148711..811a953a093b51 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -869,6 +869,19 @@ def test_invalid_env(self): stdout, stderr = p.communicate() self.assertEqual(stdout, b"orange=lemon") + @unittest.skipUnless(sys.platform == "win32", "Windows only issue") + def test_win32_invalid_env(self): + # '=' in the environment variable name + newenv = os.environ.copy() + newenv["FRUIT=VEGETABLE"] = "cabbage" + with self.assertRaises(ValueError): + subprocess.Popen(ZERO_RETURN_CMD, env=newenv) + + newenv = os.environ.copy() + newenv["==FRUIT"] = "cabbage" + with self.assertRaises(ValueError): + subprocess.Popen(ZERO_RETURN_CMD, env=newenv) + def test_communicate_stdin(self): p = subprocess.Popen([sys.executable, "-c", 'import sys;' From 37fa2f2f1512c94abfabb462ce28324ed887acdf Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 4 Sep 2023 13:39:44 +0800 Subject: [PATCH 10/58] fix memory leak --- Modules/_winapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 18801306173309..ea19a1a4945e91 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -846,6 +846,7 @@ normalize_environment(PyObject* environment) { continue; } PyObject_SetItem(result, key, value); + PyMem_Free(prev_key_string); prev_key_string = key_string; } From 47155b5c9a66e93e25484885ffb80fa427e17fc3 Mon Sep 17 00:00:00 2001 From: AN Long Date: Fri, 8 Sep 2023 21:07:43 +0800 Subject: [PATCH 11/58] follow PEP7 --- Modules/_winapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index ea19a1a4945e91..70a0e56d4d7f95 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -786,7 +786,8 @@ static PyMethodDef sortenvironmentkey_def = { }; static PyObject * -normalize_environment(PyObject* environment) { +normalize_environment(PyObject* environment) +{ PyObject *result, *keys, *keyfunc, *sort, *args, *kwargs; keys = PyMapping_Keys(environment); From a204740a0514dd890dd4073455eb58d01ae41cbf Mon Sep 17 00:00:00 2001 From: AN Long Date: Fri, 8 Sep 2023 22:17:46 +0800 Subject: [PATCH 12/58] add error check --- Modules/_winapi.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 70a0e56d4d7f95..aae799ff5b3d06 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -796,20 +796,43 @@ normalize_environment(PyObject* environment) } keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); + if (keyfunc == NULL) { + goto error; + } sort = PyObject_GetAttrString(keys, "sort"); + if (sort == NULL) { + goto error; + } args = PyTuple_New(0); + if (args == NULL) { + goto error; + } kwargs = PyDict_New(); - PyDict_SetItemString(kwargs, "key", keyfunc); + if (kwargs == NULL) { + goto error; + } + if (PyDict_SetItemString(kwargs, "key", keyfunc) < 0) { + goto error; + } if (PyObject_Call(sort, args, kwargs) == NULL) { goto error; } result = PyDict_New(); + if (result == NULL) { + goto error; + } wchar_t *prev_key_string = NULL; for (int i=0; i Date: Mon, 11 Sep 2023 20:29:04 +0800 Subject: [PATCH 13/58] fix test --- Modules/_winapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index aae799ff5b3d06..66661f2ab48726 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -826,11 +826,11 @@ normalize_environment(PyObject* environment) for (int i=0; i Date: Mon, 11 Sep 2023 20:33:34 +0800 Subject: [PATCH 14/58] better cleanup in error path --- Modules/_winapi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 66661f2ab48726..a1ff61b5bef006 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -788,7 +788,8 @@ static PyMethodDef sortenvironmentkey_def = { static PyObject * normalize_environment(PyObject* environment) { - PyObject *result, *keys, *keyfunc, *sort, *args, *kwargs; + PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *sort = NULL, + *args = NULL, *kwargs = NULL; keys = PyMapping_Keys(environment); if (keys == NULL) { @@ -883,11 +884,11 @@ normalize_environment(PyObject* environment) } error: - Py_DECREF(keys); - Py_DECREF(keyfunc); - Py_DECREF(sort); - Py_DECREF(args); - Py_DECREF(kwargs); + Py_XDECREF(keys); + Py_XDECREF(keyfunc); + Py_XDECREF(sort); + Py_XDECREF(args); + Py_XDECREF(kwargs); if (prev_key_string != NULL) { PyMem_Free(prev_key_string); } From 65c84832092b764abcc989877e08fcc63ddc0716 Mon Sep 17 00:00:00 2001 From: AN Long Date: Wed, 13 Sep 2023 19:08:41 +0800 Subject: [PATCH 15/58] fix a mem leak --- Modules/_winapi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index a1ff61b5bef006..4e11139b128357 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -838,16 +838,12 @@ normalize_environment(PyObject* environment) if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "environment can only contain strings"); - Py_DECREF(result); - result = NULL; goto error; } if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 || PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1) { PyErr_SetString(PyExc_ValueError, "embedded null character"); - Py_DECREF(result); - result = NULL; goto error; } /* Search from index 1 because on Windows starting '=' is allowed for @@ -856,8 +852,6 @@ normalize_environment(PyObject* environment) PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_DECREF(result); - result = NULL; goto error; } @@ -892,6 +886,10 @@ normalize_environment(PyObject* environment) if (prev_key_string != NULL) { PyMem_Free(prev_key_string); } + if (PyErr_Occurred()) { + Py_XDECREF(result); + result = NULL; + } return result; } From 2d2fd4d6e40e2530bfad7a150bfa6b1e83c77af5 Mon Sep 17 00:00:00 2001 From: AN Long Date: Wed, 13 Sep 2023 21:19:38 +0800 Subject: [PATCH 16/58] refactor error handling --- Modules/_winapi.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 4e11139b128357..6858ea62f8e92e 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -828,22 +828,30 @@ normalize_environment(PyObject* environment) for (int i=0; i Date: Tue, 19 Sep 2023 18:41:11 +0800 Subject: [PATCH 17/58] fix one off iteration and add test --- Lib/test/test_subprocess.py | 8 ++++++++ Modules/_winapi.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 52454c8b9103f9..5da768a2617360 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -830,6 +830,14 @@ def is_env_var_to_ignore(n): if not is_env_var_to_ignore(k)] self.assertEqual(child_env_names, []) + def test_one_env(self): + newenv = {'fruit': 'orange'} + with subprocess.Popen(["CMD", "/c", "SET", "fruit"], + stdout=subprocess.PIPE, + env=newenv) as p: + stdout, stderr = p.communicate() + self.assertEqual(stdout, b"fruit=orange\r\n") + def test_invalid_cmd(self): # null character in the command name cmd = sys.executable + '\0' diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 6858ea62f8e92e..c22b2866fffab8 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -872,6 +872,11 @@ normalize_environment(PyObject* environment) result = NULL; goto error; } + if (PyObject_SetItem(result, key, value) < 0) { + Py_XDECREF(result); + result = NULL; + goto error; + } continue; } From da55b3b3b2bbcc989048ef2498c64baf34202dd4 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 19 Sep 2023 20:21:43 +0800 Subject: [PATCH 18/58] fix one env test on non windows platforms --- Lib/test/test_subprocess.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 5da768a2617360..989fb6c8ad9963 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -832,10 +832,11 @@ def is_env_var_to_ignore(n): def test_one_env(self): newenv = {'fruit': 'orange'} - with subprocess.Popen(["CMD", "/c", "SET", "fruit"], - stdout=subprocess.PIPE, - env=newenv) as p: - stdout, stderr = p.communicate() + cmd = ["echo", "$fruit"] + if sys.platform == "win32": + cmd = ["CMD", "/c", "SET", "fruit"] + with subprocess.Popen(cmd, stdout=subprocess.PIPE, env=newenv) as p: + stdout, _ = p.communicate() self.assertEqual(stdout, b"fruit=orange\r\n") def test_invalid_cmd(self): From bf5a55532414a7bfd74b69b3b4105cfd9d5bf7ca Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 24 Sep 2023 21:02:51 +0800 Subject: [PATCH 19/58] using vector call --- Lib/keyword.py | 128 +++++++++++++++++++++++----------------------- Modules/_winapi.c | 27 +++------- 2 files changed, 72 insertions(+), 83 deletions(-) diff --git a/Lib/keyword.py b/Lib/keyword.py index e22c837835e740..124ee960c9fcb8 100644 --- a/Lib/keyword.py +++ b/Lib/keyword.py @@ -1,64 +1,64 @@ -"""Keywords (from "Grammar/python.gram") - -This file is automatically generated; please don't muck it up! - -To update the symbols in this file, 'cd' to the top directory of -the python source tree and run: - - PYTHONPATH=Tools/peg_generator python3 -m pegen.keywordgen \ - Grammar/python.gram \ - Grammar/Tokens \ - Lib/keyword.py - -Alternatively, you can run 'make regen-keyword'. -""" - -__all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] - -kwlist = [ - 'False', - 'None', - 'True', - 'and', - 'as', - 'assert', - 'async', - 'await', - 'break', - 'class', - 'continue', - 'def', - 'del', - 'elif', - 'else', - 'except', - 'finally', - 'for', - 'from', - 'global', - 'if', - 'import', - 'in', - 'is', - 'lambda', - 'nonlocal', - 'not', - 'or', - 'pass', - 'raise', - 'return', - 'try', - 'while', - 'with', - 'yield' -] - -softkwlist = [ - '_', - 'case', - 'match', - 'type' -] - -iskeyword = frozenset(kwlist).__contains__ -issoftkeyword = frozenset(softkwlist).__contains__ +"""Keywords (from "Grammar/python.gram") + +This file is automatically generated; please don't muck it up! + +To update the symbols in this file, 'cd' to the top directory of +the python source tree and run: + + PYTHONPATH=Tools/peg_generator python3 -m pegen.keywordgen \ + Grammar/python.gram \ + Grammar/Tokens \ + Lib/keyword.py + +Alternatively, you can run 'make regen-keyword'. +""" + +__all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] + +kwlist = [ + 'False', + 'None', + 'True', + 'and', + 'as', + 'assert', + 'async', + 'await', + 'break', + 'class', + 'continue', + 'def', + 'del', + 'elif', + 'else', + 'except', + 'finally', + 'for', + 'from', + 'global', + 'if', + 'import', + 'in', + 'is', + 'lambda', + 'nonlocal', + 'not', + 'or', + 'pass', + 'raise', + 'return', + 'try', + 'while', + 'with', + 'yield' +] + +softkwlist = [ + '_', + 'case', + 'match', + 'type' +] + +iskeyword = frozenset(kwlist).__contains__ +issoftkeyword = frozenset(softkwlist).__contains__ diff --git a/Modules/_winapi.c b/Modules/_winapi.c index c22b2866fffab8..f1f5148e0819fc 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -788,8 +788,7 @@ static PyMethodDef sortenvironmentkey_def = { static PyObject * normalize_environment(PyObject* environment) { - PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *sort = NULL, - *args = NULL, *kwargs = NULL; + PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *kwnames = NULL; keys = PyMapping_Keys(environment); if (keys == NULL) { @@ -800,22 +799,13 @@ normalize_environment(PyObject* environment) if (keyfunc == NULL) { goto error; } - sort = PyObject_GetAttrString(keys, "sort"); - if (sort == NULL) { + kwnames = PyTuple_New(1); + if (kwnames == NULL) { goto error; } - args = PyTuple_New(0); - if (args == NULL) { - goto error; - } - kwargs = PyDict_New(); - if (kwargs == NULL) { - goto error; - } - if (PyDict_SetItemString(kwargs, "key", keyfunc) < 0) { - goto error; - } - if (PyObject_Call(sort, args, kwargs) == NULL) { + assert(PyTuple_SetItem(kwnames, 0, PyUnicode_FromString("key")) == 0); + PyObject *args[] = { keys, keyfunc }; + if (PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames) == NULL) { goto error; } @@ -898,12 +888,11 @@ normalize_environment(PyObject* environment) prev_key_string = key_string; } +cleanup: error: Py_XDECREF(keys); Py_XDECREF(keyfunc); - Py_XDECREF(sort); - Py_XDECREF(args); - Py_XDECREF(kwargs); + Py_XDECREF(kwnames); if (prev_key_string != NULL) { PyMem_Free(prev_key_string); } From 66fddbe95801c7e1e598416af388e0d5db34d132 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 24 Sep 2023 21:16:48 +0800 Subject: [PATCH 20/58] fix test on none windows platforms --- Lib/test/test_subprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 989fb6c8ad9963..505f51cea5ba05 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -832,12 +832,12 @@ def is_env_var_to_ignore(n): def test_one_env(self): newenv = {'fruit': 'orange'} - cmd = ["echo", "$fruit"] + cmd = ["echo", "fruite=$fruit"] if sys.platform == "win32": cmd = ["CMD", "/c", "SET", "fruit"] with subprocess.Popen(cmd, stdout=subprocess.PIPE, env=newenv) as p: stdout, _ = p.communicate() - self.assertEqual(stdout, b"fruit=orange\r\n") + self.assertTrue(stdout.startswith(b"fruit=orange")) def test_invalid_cmd(self): # null character in the command name From 2b82368b2d2e0b29c54850c770acd35ea2c4894f Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 24 Sep 2023 21:36:09 +0800 Subject: [PATCH 21/58] fix typo in test --- Lib/test/test_subprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 505f51cea5ba05..64967dffcfb667 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -832,7 +832,7 @@ def is_env_var_to_ignore(n): def test_one_env(self): newenv = {'fruit': 'orange'} - cmd = ["echo", "fruite=$fruit"] + cmd = ["echo", "fruit=$fruit"] if sys.platform == "win32": cmd = ["CMD", "/c", "SET", "fruit"] with subprocess.Popen(cmd, stdout=subprocess.PIPE, env=newenv) as p: From 5c581ea20a8a195adc90804c7ae7c1cc03a268ad Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 25 Sep 2023 14:59:58 +0800 Subject: [PATCH 22/58] fix test on linux --- Lib/test/test_subprocess.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 64967dffcfb667..51d93fd87249b0 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -832,7 +832,9 @@ def is_env_var_to_ignore(n): def test_one_env(self): newenv = {'fruit': 'orange'} - cmd = ["echo", "fruit=$fruit"] + cmd = [sys.executable, '-c', + 'import sys,os;' + 'sys.stdout.write("fruit="+os.getenv("fruit"))'] if sys.platform == "win32": cmd = ["CMD", "/c", "SET", "fruit"] with subprocess.Popen(cmd, stdout=subprocess.PIPE, env=newenv) as p: From 6b5d1da505b8347c953bd6c50a2bf622fef39b0a Mon Sep 17 00:00:00 2001 From: AN Long Date: Thu, 5 Oct 2023 00:32:35 +0800 Subject: [PATCH 23/58] revert line end modify and align codes with pep7 --- Lib/keyword.py | 128 +++++++++++++++++++++++----------------------- Modules/_winapi.c | 7 +-- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/Lib/keyword.py b/Lib/keyword.py index 124ee960c9fcb8..e22c837835e740 100644 --- a/Lib/keyword.py +++ b/Lib/keyword.py @@ -1,64 +1,64 @@ -"""Keywords (from "Grammar/python.gram") - -This file is automatically generated; please don't muck it up! - -To update the symbols in this file, 'cd' to the top directory of -the python source tree and run: - - PYTHONPATH=Tools/peg_generator python3 -m pegen.keywordgen \ - Grammar/python.gram \ - Grammar/Tokens \ - Lib/keyword.py - -Alternatively, you can run 'make regen-keyword'. -""" - -__all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] - -kwlist = [ - 'False', - 'None', - 'True', - 'and', - 'as', - 'assert', - 'async', - 'await', - 'break', - 'class', - 'continue', - 'def', - 'del', - 'elif', - 'else', - 'except', - 'finally', - 'for', - 'from', - 'global', - 'if', - 'import', - 'in', - 'is', - 'lambda', - 'nonlocal', - 'not', - 'or', - 'pass', - 'raise', - 'return', - 'try', - 'while', - 'with', - 'yield' -] - -softkwlist = [ - '_', - 'case', - 'match', - 'type' -] - -iskeyword = frozenset(kwlist).__contains__ -issoftkeyword = frozenset(softkwlist).__contains__ +"""Keywords (from "Grammar/python.gram") + +This file is automatically generated; please don't muck it up! + +To update the symbols in this file, 'cd' to the top directory of +the python source tree and run: + + PYTHONPATH=Tools/peg_generator python3 -m pegen.keywordgen \ + Grammar/python.gram \ + Grammar/Tokens \ + Lib/keyword.py + +Alternatively, you can run 'make regen-keyword'. +""" + +__all__ = ["iskeyword", "issoftkeyword", "kwlist", "softkwlist"] + +kwlist = [ + 'False', + 'None', + 'True', + 'and', + 'as', + 'assert', + 'async', + 'await', + 'break', + 'class', + 'continue', + 'def', + 'del', + 'elif', + 'else', + 'except', + 'finally', + 'for', + 'from', + 'global', + 'if', + 'import', + 'in', + 'is', + 'lambda', + 'nonlocal', + 'not', + 'or', + 'pass', + 'raise', + 'return', + 'try', + 'while', + 'with', + 'yield' +] + +softkwlist = [ + '_', + 'case', + 'match', + 'type' +] + +iskeyword = frozenset(kwlist).__contains__ +issoftkeyword = frozenset(softkwlist).__contains__ diff --git a/Modules/_winapi.c b/Modules/_winapi.c index f1f5148e0819fc..53d3e32559f7fc 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -774,7 +774,9 @@ gethandle(PyObject* obj, const char* name) return ret; } -static PyObject* sortenvironmentkey(PyObject *module, PyObject *item) { +static PyObject* +sortenvironmentkey(PyObject *module, PyObject *item) +{ return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, item); } @@ -782,7 +784,7 @@ static PyMethodDef sortenvironmentkey_def = { "sortenvironmentkey", _PyCFunction_CAST(sortenvironmentkey), METH_O, - "" + "", }; static PyObject * @@ -888,7 +890,6 @@ normalize_environment(PyObject* environment) prev_key_string = key_string; } -cleanup: error: Py_XDECREF(keys); Py_XDECREF(keyfunc); From bcd8910fad9c82d60d341a115fcceac7465fd36a Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:29:33 +0800 Subject: [PATCH 24/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 53d3e32559f7fc..c7dc446a7dd38f 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -879,6 +879,7 @@ normalize_environment(PyObject* environment) goto error; } if (CompareStringOrdinal(prev_key_string, -1, key_string, -1, TRUE) == CSTR_EQUAL) { + PyMem_Free(key_string); continue; } if (PyObject_SetItem(result, key, value) < 0) { From 3423e13807618df0c559fa43655a0e24ef430fd8 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:30:34 +0800 Subject: [PATCH 25/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index c7dc446a7dd38f..460d24e8c9de4d 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -891,7 +891,11 @@ normalize_environment(PyObject* environment) prev_key_string = key_string; } + goto cleanup; error: + Py_XDECREF(result); + result = NULL; +cleanup: Py_XDECREF(keys); Py_XDECREF(keyfunc); Py_XDECREF(kwnames); From 03a4f7e927445378f714313b6bbf048360b5b049 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:31:23 +0800 Subject: [PATCH 26/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 460d24e8c9de4d..583717b41b1e72 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -883,8 +883,6 @@ normalize_environment(PyObject* environment) continue; } if (PyObject_SetItem(result, key, value) < 0) { - Py_XDECREF(result); - result = NULL; goto error; } PyMem_Free(prev_key_string); From 186d718f984c14ff5b2a74296695ff00cad952ed Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:31:43 +0800 Subject: [PATCH 27/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 583717b41b1e72..251a7cf6398e1b 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -874,8 +874,6 @@ normalize_environment(PyObject* environment) wchar_t *key_string = PyUnicode_AsWideCharString(key, NULL); if (key_string == NULL) { - Py_XDECREF(result); - result = NULL; goto error; } if (CompareStringOrdinal(prev_key_string, -1, key_string, -1, TRUE) == CSTR_EQUAL) { From 8b074dff97199621856050410f95434929aca152 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:31:55 +0800 Subject: [PATCH 28/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 251a7cf6398e1b..db9340d929f8ee 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -865,8 +865,6 @@ normalize_environment(PyObject* environment) goto error; } if (PyObject_SetItem(result, key, value) < 0) { - Py_XDECREF(result); - result = NULL; goto error; } continue; From b675260de8c82c3a56c141ac4d8a00dcad43f2b1 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:32:16 +0800 Subject: [PATCH 29/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index db9340d929f8ee..066a47bd797cc6 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -860,8 +860,6 @@ normalize_environment(PyObject* environment) if (i == 0) { prev_key_string = PyUnicode_AsWideCharString(key, NULL); if (prev_key_string == NULL) { - Py_XDECREF(result); - result = NULL; goto error; } if (PyObject_SetItem(result, key, value) < 0) { From fb93eb1c6ce01b8ec83f79187fbd06abaa1c718d Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:32:32 +0800 Subject: [PATCH 30/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 066a47bd797cc6..06a95b688caf77 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -852,8 +852,6 @@ normalize_environment(PyObject* environment) PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - Py_XDECREF(result); - result = NULL; goto error; } From f9d97eb5d165137ddbd54fd463b4f16fcf7e4611 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:32:51 +0800 Subject: [PATCH 31/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 06a95b688caf77..ffb2f3669b817b 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -842,8 +842,6 @@ normalize_environment(PyObject* environment) PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1) { PyErr_SetString(PyExc_ValueError, "embedded null character"); - Py_XDECREF(result); - result = NULL; goto error; } /* Search from index 1 because on Windows starting '=' is allowed for From 6f3b7ce33e148b72dbdc2542744fcb474c7fe259 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:33:10 +0800 Subject: [PATCH 32/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index ffb2f3669b817b..d12ada8e0f2ec3 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -834,8 +834,6 @@ normalize_environment(PyObject* environment) if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "environment can only contain strings"); - Py_XDECREF(result); - result = NULL; goto error; } if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 || From b9b8d6eed782e3fc75e14e535f19c31c6a2b6ac8 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:33:53 +0800 Subject: [PATCH 33/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index d12ada8e0f2ec3..10c6129b7e503a 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -826,8 +826,6 @@ normalize_environment(PyObject* environment) } PyObject* value = PyObject_GetItem(environment, key); if (value == NULL) { - Py_XDECREF(result); - result = NULL; goto error; } From 5fd7ebf8a976a181ea07bdb8bd129b43dec8b388 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 16:34:52 +0800 Subject: [PATCH 34/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 10c6129b7e503a..c5a53ba10235a1 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -820,8 +820,6 @@ normalize_environment(PyObject* environment) for (int i=0; i Date: Sat, 6 Jan 2024 16:39:39 +0800 Subject: [PATCH 35/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index c5a53ba10235a1..0da3e10e14e3c2 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -801,11 +801,10 @@ normalize_environment(PyObject* environment) if (keyfunc == NULL) { goto error; } - kwnames = PyTuple_New(1); + kwnames = Py_BuildValue("(s)", "key"); if (kwnames == NULL) { goto error; } - assert(PyTuple_SetItem(kwnames, 0, PyUnicode_FromString("key")) == 0); PyObject *args[] = { keys, keyfunc }; if (PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames) == NULL) { goto error; From cbdfa84bd8b96975cc51af12d77ce7d9ab7b8705 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 17:25:31 +0800 Subject: [PATCH 36/58] Update Lib/test/test_subprocess.py Co-authored-by: Steve Dower --- Lib/test/test_subprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 51d93fd87249b0..88d5d52ce4ff99 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -797,7 +797,7 @@ def test_win32_duplicate_envs(self): stdout=subprocess.PIPE, env=newenv) as p: stdout, stderr = p.communicate() - self.assertEqual(stdout, b"fRUit=cherry\r\n") + self.assertEqual(stdout.strip(), b"frUit=banana") # Windows requires at least the SYSTEMROOT environment variable to start # Python From 8748103a143ba41730dd469cb9f873e8e7ee8dda Mon Sep 17 00:00:00 2001 From: AN Long Date: Sat, 6 Jan 2024 20:12:13 +0800 Subject: [PATCH 37/58] only keep the last duplicated environment key --- Modules/_winapi.c | 66 ++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0da3e10e14e3c2..18806d1c2a8b51 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -790,7 +790,8 @@ static PyMethodDef sortenvironmentkey_def = { static PyObject * normalize_environment(PyObject* environment) { - PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *kwnames = NULL; + PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *kwnames = NULL, + *dedupped_keys = NULL; keys = PyMapping_Keys(environment); if (keys == NULL) { @@ -810,17 +811,50 @@ normalize_environment(PyObject* environment) goto error; } - result = PyDict_New(); - if (result == NULL) { + dedupped_keys = PyList_New(0); + if (dedupped_keys == NULL) { goto error; } wchar_t *prev_key_string = NULL; - - for (int i=0; i=0; i--) { PyObject *key = PyList_GET_ITEM(keys, i); if (key == NULL) { goto error; } + if (i == PyList_GET_SIZE(keys)) { + prev_key_string = PyUnicode_AsWideCharString(key, NULL); + if (prev_key_string == NULL) { + goto error; + } + if (PyList_Insert(dedupped_keys, 0, key) < 0) { + goto error; + } + continue; + } + wchar_t *key_string = PyUnicode_AsWideCharString(key, NULL); + if (key_string == NULL) { + goto error; + } + if (CompareStringOrdinal(prev_key_string, -1, key_string, -1, TRUE) == CSTR_EQUAL) { + PyMem_Free(key_string); + continue; + } + if (PyList_Insert(dedupped_keys, 0, key) < 0) { + goto error; + } + PyMem_Free(prev_key_string); + prev_key_string = key_string; + } + + result = PyDict_New(); + if (result == NULL) { + goto error; + } + for (int i=0; i Date: Sat, 6 Jan 2024 23:58:24 +0800 Subject: [PATCH 38/58] split the normalize_environment function into two --- Modules/_winapi.c | 64 +++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 18806d1c2a8b51..d536a91d696b67 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -777,7 +777,8 @@ gethandle(PyObject* obj, const char* name) static PyObject* sortenvironmentkey(PyObject *module, PyObject *item) { - return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE, item); + return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, + LCMAP_UPPERCASE, item); } static PyMethodDef sortenvironmentkey_def = { @@ -788,16 +789,12 @@ static PyMethodDef sortenvironmentkey_def = { }; static PyObject * -normalize_environment(PyObject* environment) +normalize_environment_keys(PyObject *keys) { - PyObject *result = NULL, *keys = NULL, *keyfunc = NULL, *kwnames = NULL, - *dedupped_keys = NULL; - - keys = PyMapping_Keys(environment); - if (keys == NULL) { - return NULL; - } + PyObject *keyfunc = NULL, *kwnames = NULL, *result = NULL; + wchar_t *prev_key_string = NULL; + // Sort the keys. keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); if (keyfunc == NULL) { goto error; @@ -811,11 +808,11 @@ normalize_environment(PyObject* environment) goto error; } - dedupped_keys = PyList_New(0); - if (dedupped_keys == NULL) { + // Remove duplicated keys and only keep the last inserted one. + result = PyList_New(0); + if (result == NULL) { goto error; } - wchar_t *prev_key_string = NULL; for (Py_ssize_t i=PyList_GET_SIZE(keys)-1; i>=0; i--) { PyObject *key = PyList_GET_ITEM(keys, i); if (key == NULL) { @@ -826,7 +823,7 @@ normalize_environment(PyObject* environment) if (prev_key_string == NULL) { goto error; } - if (PyList_Insert(dedupped_keys, 0, key) < 0) { + if (PyList_Insert(result, 0, key) < 0) { goto error; } continue; @@ -839,19 +836,48 @@ normalize_environment(PyObject* environment) PyMem_Free(key_string); continue; } - if (PyList_Insert(dedupped_keys, 0, key) < 0) { + if (PyList_Insert(result, 0, key) < 0) { goto error; } PyMem_Free(prev_key_string); prev_key_string = key_string; } + goto cleanup; +error: + Py_XDECREF(result); + result = NULL; +cleanup: + Py_XDECREF(keyfunc); + Py_XDECREF(kwnames); + if (prev_key_string != NULL) { + PyMem_Free(prev_key_string); + } + + return result; +} + +static PyObject * +normalize_environment(PyObject* environment) +{ + PyObject *result = NULL, *keys = NULL, *normalized_keys = NULL; + + keys = PyMapping_Keys(environment); + if (keys == NULL) { + return NULL; + } + + normalized_keys = normalize_environment_keys(keys); + if (normalized_keys == NULL) { + goto error; + } + result = PyDict_New(); if (result == NULL) { goto error; } - for (int i=0; i Date: Sun, 7 Jan 2024 16:42:21 +0800 Subject: [PATCH 39/58] Update Lib/test/test_subprocess.py Co-authored-by: Pieter Eendebak --- Lib/test/test_subprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 88d5d52ce4ff99..4d974608e36f7d 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -830,7 +830,7 @@ def is_env_var_to_ignore(n): if not is_env_var_to_ignore(k)] self.assertEqual(child_env_names, []) - def test_one_env(self): + def test_one_environment_variable(self): newenv = {'fruit': 'orange'} cmd = [sys.executable, '-c', 'import sys,os;' From d02319e08aa7e8e0ffcddbb0579ff440750653a0 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 7 Jan 2024 16:53:11 +0800 Subject: [PATCH 40/58] remove the error check for PyList_GET_ITEM --- Modules/_winapi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index d536a91d696b67..15f7c5278995d4 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -815,9 +815,6 @@ normalize_environment_keys(PyObject *keys) } for (Py_ssize_t i=PyList_GET_SIZE(keys)-1; i>=0; i--) { PyObject *key = PyList_GET_ITEM(keys, i); - if (key == NULL) { - goto error; - } if (i == PyList_GET_SIZE(keys)) { prev_key_string = PyUnicode_AsWideCharString(key, NULL); if (prev_key_string == NULL) { From d1c794b8070abe00e5e7d71b529219dadbef0654 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 7 Jan 2024 17:07:56 +0800 Subject: [PATCH 41/58] decref the vectorcall result --- Modules/_winapi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 15f7c5278995d4..60cba252679817 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -804,9 +804,11 @@ normalize_environment_keys(PyObject *keys) goto error; } PyObject *args[] = { keys, keyfunc }; - if (PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames) == NULL) { + PyObject *r = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); + if (r == NULL) { goto error; } + Py_DECREF(r); // Remove duplicated keys and only keep the last inserted one. result = PyList_New(0); From 17634211b675ce2c138dded43d4f6879bbb5aed2 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 7 Jan 2024 17:32:39 +0800 Subject: [PATCH 42/58] split normalze_keys into sort_keys and dedup_keys --- Modules/_winapi.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 60cba252679817..4eada998c74ff6 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -788,32 +788,45 @@ static PyMethodDef sortenvironmentkey_def = { "", }; -static PyObject * -normalize_environment_keys(PyObject *keys) +bool +sort_environment_keys(PyObject *keys) { - PyObject *keyfunc = NULL, *kwnames = NULL, *result = NULL; - wchar_t *prev_key_string = NULL; + PyObject *keyfunc = NULL, *kwnames = NULL; + bool result = false; - // Sort the keys. keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); if (keyfunc == NULL) { - goto error; + return false; } kwnames = Py_BuildValue("(s)", "key"); if (kwnames == NULL) { - goto error; + goto cleanup; } PyObject *args[] = { keys, keyfunc }; - PyObject *r = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); - if (r == NULL) { - goto error; + PyObject *ret = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); + if (ret == NULL) { + goto cleanup; } - Py_DECREF(r); + Py_DECREF(ret); + + result = true; + +cleanup: + Py_XDECREF(keyfunc); + Py_XDECREF(kwnames); + + return result; +} + +static PyObject * +dedup_environment_keys(PyObject *keys) +{ + PyObject *result = NULL; + wchar_t *prev_key_string = NULL; - // Remove duplicated keys and only keep the last inserted one. result = PyList_New(0); if (result == NULL) { - goto error; + return NULL; } for (Py_ssize_t i=PyList_GET_SIZE(keys)-1; i>=0; i--) { PyObject *key = PyList_GET_ITEM(keys, i); @@ -847,8 +860,6 @@ normalize_environment_keys(PyObject *keys) Py_XDECREF(result); result = NULL; cleanup: - Py_XDECREF(keyfunc); - Py_XDECREF(kwnames); if (prev_key_string != NULL) { PyMem_Free(prev_key_string); } @@ -866,7 +877,10 @@ normalize_environment(PyObject* environment) return NULL; } - normalized_keys = normalize_environment_keys(keys); + if (!sort_environment_keys(keys)) { + goto error; + } + normalized_keys = dedup_environment_keys(keys); if (normalized_keys == NULL) { goto error; } From dbbaf1bcd82dbc8caf4e9c230fbc4c118f7ca565 Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 7 Jan 2024 23:51:52 +0800 Subject: [PATCH 43/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 4eada998c74ff6..beda162fe8dc9c 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -788,7 +788,7 @@ static PyMethodDef sortenvironmentkey_def = { "", }; -bool +static bool sort_environment_keys(PyObject *keys) { PyObject *keyfunc = NULL, *kwnames = NULL; From 176e90d0d6f37bfba33586468a9d75d4f6979007 Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 8 Jan 2024 19:24:10 +0800 Subject: [PATCH 44/58] refactor sort_environment_keys to remove the goto error stuff --- Modules/_winapi.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index beda162fe8dc9c..d681edfadc15cf 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -791,31 +791,25 @@ static PyMethodDef sortenvironmentkey_def = { static bool sort_environment_keys(PyObject *keys) { - PyObject *keyfunc = NULL, *kwnames = NULL; - bool result = false; - - keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); + PyObject *keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); if (keyfunc == NULL) { return false; } - kwnames = Py_BuildValue("(s)", "key"); + PyObject *kwnames = Py_BuildValue("(s)", "key"); if (kwnames == NULL) { - goto cleanup; + Py_DECREF(keyfunc); + return false; } PyObject *args[] = { keys, keyfunc }; PyObject *ret = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); + Py_DECREF(keyfunc); + Py_DECREF(kwnames); if (ret == NULL) { - goto cleanup; + return false; } Py_DECREF(ret); - result = true; - -cleanup: - Py_XDECREF(keyfunc); - Py_XDECREF(kwnames); - - return result; + return true; } static PyObject * From d08808397a6c224c976aca7ee8def901606b52be Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 8 Jan 2024 20:57:48 +0800 Subject: [PATCH 45/58] refactor the dedup_environment_keys to get rid of the goto error stuff --- Modules/_winapi.c | 71 +++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index d681edfadc15cf..420ad4825e807b 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -812,50 +812,61 @@ sort_environment_keys(PyObject *keys) return true; } +static bool +compare_string_ordinal(PyObject *str1, PyObject *str2, int *result) +{ + wchar_t *s1 = PyUnicode_AsWideCharString(str1, NULL); + if (s1 == NULL) { + return false; + } + wchar_t *s2 = PyUnicode_AsWideCharString(str2, NULL); + if (s2 == NULL) { + PyMem_Free(s1); + return false; + } + *result = CompareStringOrdinal(s1, -1, s2, -1, TRUE); + PyMem_Free(s1); + PyMem_Free(s2); + return true; +} + static PyObject * dedup_environment_keys(PyObject *keys) { - PyObject *result = NULL; - wchar_t *prev_key_string = NULL; - - result = PyList_New(0); + PyObject *result = PyList_New(0); if (result == NULL) { return NULL; } - for (Py_ssize_t i=PyList_GET_SIZE(keys)-1; i>=0; i--) { + + // Iterate over the pre-ordered keys, check whether the current key is equal + // to the next key (ignoring case), if different, insert the current value + // into the result list. If they are equal, do nothing because we always + // want to keep the last inserted one. + for (Py_ssize_t i=0; i Date: Mon, 8 Jan 2024 21:10:22 +0800 Subject: [PATCH 46/58] fix a memory leak in `normalize_environment` --- Modules/_winapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 420ad4825e807b..0e1a82e159843e 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -935,6 +935,7 @@ normalize_environment(PyObject* environment) result = NULL; cleanup: Py_XDECREF(keys); + Py_XDECREF(normalized_keys); return result; } From a2dab935520c749af807bfac81f942b2d9de5522 Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 8 Jan 2024 21:14:58 +0800 Subject: [PATCH 47/58] revert the commit that moves key validation codes to the original place --- Modules/_winapi.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0e1a82e159843e..0210c36def5f14 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -904,26 +904,6 @@ normalize_environment(PyObject* environment) goto error; } - if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "environment can only contain strings"); - goto error; - } - if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 || - PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto error; - } - /* Search from index 1 because on Windows starting '=' is allowed for - defining hidden environment variables. */ - if (PyUnicode_GET_LENGTH(key) == 0 || - PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1) - { - PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); - goto error; - } - if (PyObject_SetItem(result, key, value) < 0) { goto error; } @@ -992,6 +972,26 @@ getenvironment(PyObject* environment) PyObject* value = PyList_GET_ITEM(values, i); Py_ssize_t size; + if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "environment can only contain strings"); + goto error; + } + if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 || + PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto error; + } + /* Search from index 1 because on Windows starting '=' is allowed for + defining hidden environment variables. */ + if (PyUnicode_GET_LENGTH(key) == 0 || + PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1) + { + PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); + goto error; + } + size = PyUnicode_AsWideChar(key, NULL, 0); assert(size > 1); if (totalsize > PY_SSIZE_T_MAX - size) { From 6a2bbee66ea74448e04af0a18fa38c5174e8afa6 Mon Sep 17 00:00:00 2001 From: AN Long Date: Mon, 8 Jan 2024 21:59:57 +0800 Subject: [PATCH 48/58] fixed a memory leak --- Lib/test/test_subprocess.py | 2 +- Modules/_winapi.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 4d974608e36f7d..873e5c200a25fe 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -796,7 +796,7 @@ def test_win32_duplicate_envs(self): with subprocess.Popen(["CMD", "/c", "SET", "fruit"], stdout=subprocess.PIPE, env=newenv) as p: - stdout, stderr = p.communicate() + stdout, _ = p.communicate() self.assertEqual(stdout.strip(), b"frUit=banana") # Windows requires at least the SYSTEMROOT environment variable to start diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 0210c36def5f14..50e69f1cf2fb5e 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -907,6 +907,7 @@ normalize_environment(PyObject* environment) if (PyObject_SetItem(result, key, value) < 0) { goto error; } + Py_DECREF(value); } goto cleanup; From 22548ccedf26f4d8ae310830a0cf74d608164c9a Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 15:08:33 +0800 Subject: [PATCH 49/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 50e69f1cf2fb5e..87ef784dbca48c 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -842,7 +842,7 @@ dedup_environment_keys(PyObject *keys) // to the next key (ignoring case), if different, insert the current value // into the result list. If they are equal, do nothing because we always // want to keep the last inserted one. - for (Py_ssize_t i=0; i Date: Tue, 9 Jan 2024 15:08:46 +0800 Subject: [PATCH 50/58] Update Modules/_winapi.c Co-authored-by: Steve Dower --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 87ef784dbca48c..93e5f00803e52e 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -894,7 +894,7 @@ normalize_environment(PyObject* environment) if (result == NULL) { goto error; } - for (int i=0; i Date: Tue, 9 Jan 2024 16:59:09 +0800 Subject: [PATCH 51/58] using int as return value rather than bool --- Modules/_winapi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 93e5f00803e52e..2fd19c1519fa4c 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -788,46 +788,46 @@ static PyMethodDef sortenvironmentkey_def = { "", }; -static bool +static int sort_environment_keys(PyObject *keys) { PyObject *keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); if (keyfunc == NULL) { - return false; + return -1; } PyObject *kwnames = Py_BuildValue("(s)", "key"); if (kwnames == NULL) { Py_DECREF(keyfunc); - return false; + return -1; } PyObject *args[] = { keys, keyfunc }; PyObject *ret = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); Py_DECREF(keyfunc); Py_DECREF(kwnames); if (ret == NULL) { - return false; + return -1; } Py_DECREF(ret); - return true; + return 0; } -static bool +static int compare_string_ordinal(PyObject *str1, PyObject *str2, int *result) { wchar_t *s1 = PyUnicode_AsWideCharString(str1, NULL); if (s1 == NULL) { - return false; + return -1; } wchar_t *s2 = PyUnicode_AsWideCharString(str2, NULL); if (s2 == NULL) { PyMem_Free(s1); - return false; + return -1; } *result = CompareStringOrdinal(s1, -1, s2, -1, TRUE); PyMem_Free(s1); PyMem_Free(s2); - return true; + return 0; } static PyObject * @@ -856,7 +856,7 @@ dedup_environment_keys(PyObject *keys) PyObject *next_key = PyList_GET_ITEM(keys, i + 1); int compare_result; - if (!compare_string_ordinal(key, next_key, &compare_result)) { + if (compare_string_ordinal(key, next_key, &compare_result) < 0) { Py_DECREF(result); return NULL; } @@ -882,7 +882,7 @@ normalize_environment(PyObject* environment) return NULL; } - if (!sort_environment_keys(keys)) { + if (sort_environment_keys(keys) < 0) { goto error; } normalized_keys = dedup_environment_keys(keys); From b053e2abfbe2edf6c8fc8c2c4e3d8ba77d7a2891 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 19:34:22 +0800 Subject: [PATCH 52/58] get rid of the goto error in normalize_environment --- Modules/_winapi.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 2fd19c1519fa4c..a14f05b7bbe5f1 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -875,48 +875,47 @@ dedup_environment_keys(PyObject *keys) static PyObject * normalize_environment(PyObject* environment) { - PyObject *result = NULL, *keys = NULL, *normalized_keys = NULL; - - keys = PyMapping_Keys(environment); + PyObject *keys = PyMapping_Keys(environment); if (keys == NULL) { return NULL; } if (sort_environment_keys(keys) < 0) { - goto error; + Py_DECREF(keys); + return NULL; } - normalized_keys = dedup_environment_keys(keys); + + PyObject *normalized_keys = dedup_environment_keys(keys); + Py_DECREF(keys); if (normalized_keys == NULL) { - goto error; + return NULL; } - result = PyDict_New(); + PyObject *result = PyDict_New(); if (result == NULL) { - goto error; + Py_DECREF(normalized_keys); + return NULL; } + for (int i = 0; i < PyList_GET_SIZE(normalized_keys); i++) { PyObject *key = PyList_GET_ITEM(normalized_keys, i); - if (key == NULL) { - goto error; - } PyObject* value = PyObject_GetItem(environment, key); if (value == NULL) { - goto error; + Py_DECREF(normalized_keys); + Py_DECREF(result); + return NULL; } - if (PyObject_SetItem(result, key, value) < 0) { - goto error; - } + int ret = PyObject_SetItem(result, key, value); Py_DECREF(value); + if (ret < 0) { + Py_DECREF(normalized_keys); + Py_DECREF(result); + return NULL; + } } - goto cleanup; -error: - Py_XDECREF(result); - result = NULL; -cleanup: - Py_XDECREF(keys); - Py_XDECREF(normalized_keys); + Py_DECREF(normalized_keys); return result; } From 5dd621591f1c813691aadd4a6d4db8af18abb4a1 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:25:21 +0800 Subject: [PATCH 53/58] Update Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst Co-authored-by: Erlend E. Aasland --- .../next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst index 7206986bf1094f..37e8103c9ec34b 100644 --- a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst +++ b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst @@ -1,2 +1,2 @@ Correctly sort and remove duplicate environment variables in -``_winapi.CreateProcess``. +:py:func:`!_winapi.CreateProcess`. From be49daecc29a57df3e67d44b52a7cb65b08523b8 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:25:38 +0800 Subject: [PATCH 54/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index a14f05b7bbe5f1..e7019a0b4cbffd 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -774,7 +774,7 @@ gethandle(PyObject* obj, const char* name) return ret; } -static PyObject* +static PyObject * sortenvironmentkey(PyObject *module, PyObject *item) { return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, From 0aff1e99bbb1813bb621fe2ef1e50800541801d0 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:26:27 +0800 Subject: [PATCH 55/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index e7019a0b4cbffd..7ce6a2704a2e6f 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -782,10 +782,7 @@ sortenvironmentkey(PyObject *module, PyObject *item) } static PyMethodDef sortenvironmentkey_def = { - "sortenvironmentkey", - _PyCFunction_CAST(sortenvironmentkey), - METH_O, - "", + "sortenvironmentkey", _PyCFunction_CAST(sortenvironmentkey), METH_O, "", }; static int From 72fc36d4c0c19437292ae3f251c746d45a6e3952 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:27:21 +0800 Subject: [PATCH 56/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 7ce6a2704a2e6f..11b93b18fa1d92 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -896,7 +896,7 @@ normalize_environment(PyObject* environment) for (int i = 0; i < PyList_GET_SIZE(normalized_keys); i++) { PyObject *key = PyList_GET_ITEM(normalized_keys, i); - PyObject* value = PyObject_GetItem(environment, key); + PyObject *value = PyObject_GetItem(environment, key); if (value == NULL) { Py_DECREF(normalized_keys); Py_DECREF(result); From 725baec09b4f6c737754d11af6b66d5455e786e0 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:51:49 +0800 Subject: [PATCH 57/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 11b93b18fa1d92..08d2fc970e74b6 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -922,7 +922,9 @@ getenvironment(PyObject* environment) { Py_ssize_t i, envsize, totalsize; wchar_t *buffer = NULL, *p, *end; - PyObject *normalized_environment = NULL, *keys = NULL, *values = NULL; + PyObject *normalized_environment = NULL; + PyObject *keys = NULL; + PyObject *values = NULL; /* convert environment dictionary to windows environment string */ if (! PyMapping_Check(environment)) { From 0a308be5ba8aa80a277724eaf9bc765152383224 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 9 Jan 2024 21:52:05 +0800 Subject: [PATCH 58/58] Update Modules/_winapi.c Co-authored-by: Erlend E. Aasland --- Modules/_winapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 08d2fc970e74b6..97af4e650cd658 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -870,7 +870,7 @@ dedup_environment_keys(PyObject *keys) } static PyObject * -normalize_environment(PyObject* environment) +normalize_environment(PyObject *environment) { PyObject *keys = PyMapping_Keys(environment); if (keys == NULL) {