From 0b06d2482d77e02c5d40e221f6046c9c355458b2 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 10 Nov 2023 18:42:14 +0200 Subject: gh-111841: Fix os.putenv() and os.unsetenv() with embedded NUL on Windows (GH-111842) --- Lib/test/test_os.py | 5 ++++- Lib/test/test_posix.py | 14 +++++++------- .../Library/2023-11-08-11-50-49.gh-issue-111841.iSqdQf.rst | 2 ++ Modules/posixmodule.c | 7 ++++++- 4 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-11-08-11-50-49.gh-issue-111841.iSqdQf.rst diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b357797..c31c968 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1150,9 +1150,12 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol): def test_putenv_unsetenv_error(self): # Empty variable name is invalid. # "=" and null character are not allowed in a variable name. - for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'): + for name in ('', '=name', 'na=me', 'name='): self.assertRaises((OSError, ValueError), os.putenv, name, "value") self.assertRaises((OSError, ValueError), os.unsetenv, name) + for name in ('name\0', 'na\0me'): + self.assertRaises(ValueError, os.putenv, name, "value") + self.assertRaises(ValueError, os.unsetenv, name) if sys.platform == "win32": # On Windows, an environment variable string ("name=value" string) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 7440779..1722c84 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1011,20 +1011,20 @@ class PosixTester(unittest.TestCase): self.assertEqual(type(k), item_type) self.assertEqual(type(v), item_type) - @unittest.skipUnless(os.name == 'posix', "see bug gh-111841") def test_putenv(self): with self.assertRaises(ValueError): os.putenv('FRUIT\0VEGETABLE', 'cabbage') with self.assertRaises(ValueError): - os.putenv(b'FRUIT\0VEGETABLE', b'cabbage') - with self.assertRaises(ValueError): os.putenv('FRUIT', 'orange\0VEGETABLE=cabbage') with self.assertRaises(ValueError): - os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage') - with self.assertRaises(ValueError): os.putenv('FRUIT=ORANGE', 'lemon') - with self.assertRaises(ValueError): - os.putenv(b'FRUIT=ORANGE', b'lemon') + if os.name == 'posix': + with self.assertRaises(ValueError): + os.putenv(b'FRUIT\0VEGETABLE', b'cabbage') + with self.assertRaises(ValueError): + os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage') + with self.assertRaises(ValueError): + os.putenv(b'FRUIT=ORANGE', b'lemon') @unittest.skipUnless(hasattr(posix, 'getcwd'), 'test needs posix.getcwd()') def test_getcwd_long_pathnames(self): diff --git a/Misc/NEWS.d/next/Library/2023-11-08-11-50-49.gh-issue-111841.iSqdQf.rst b/Misc/NEWS.d/next/Library/2023-11-08-11-50-49.gh-issue-111841.iSqdQf.rst new file mode 100644 index 0000000..cd17809 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-08-11-50-49.gh-issue-111841.iSqdQf.rst @@ -0,0 +1,2 @@ +Fix truncating arguments on an embedded null character in :meth:`os.putenv` +and :meth:`os.unsetenv` on Windows. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 73b80e4..d99b533 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12280,7 +12280,6 @@ win32_putenv(PyObject *name, PyObject *value) } Py_ssize_t size; - /* PyUnicode_AsWideCharString() rejects embedded null characters */ wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); Py_DECREF(unicode); @@ -12294,6 +12293,12 @@ win32_putenv(PyObject *name, PyObject *value) PyMem_Free(env); return NULL; } + if (wcslen(env) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, + "embedded null character"); + PyMem_Free(env); + return NULL; + } /* _wputenv() and SetEnvironmentVariableW() update the environment in the Process Environment Block (PEB). _wputenv() also updates CRT 'environ' -- cgit v0.12