Make posix.putenv() raise ValueError if name is empty. diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -331,8 +331,8 @@ process and user. Set the environment variable named *key* to the string *value*. Such changes to the environment affect subprocesses started with :func:`os.system`, - :func:`popen` or :func:`fork` and :func:`execv`. Raises :exc:`ValueError` - if *key* contains an ``'='`` character. + :func:`popen` or :func:`fork` and :func:`execv`. May raise + :exc:`ValueError` if *key* is empty or contains an ``'='`` character. Availability: most flavors of Unix, Windows. diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -405,6 +405,8 @@ class EnvironTests(mapping_tests.BasicTe "PYTHONTESTVAROS=SOMETHING", "value") self.assertTrue("PYTHONTESTVAROS=SOMETHING" not in os.environ) self.assertTrue("PYTHONTESTVAROS" not in os.environ) + self.assertRaises(ValueError, os.environ.__setitem__, "", "value") + self.assertTrue("" not in os.environ) def test_os_popen_iter(self): if os.path.exists("/bin/sh"): diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -327,6 +327,7 @@ class PosixTester(unittest.TestCase): # See issue #4926 self.assertRaises(ValueError, posix.putenv, "PYTHONTESTVARB=SOMETHING", "value") + self.assertRaises(ValueError, posix.putenv, "", "value") def test_getcwd_long_pathnames(self): if hasattr(posix, 'getcwd'): diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5803,6 +5803,21 @@ posix_putenv(PyObject *self, PyObject *a s2 = PyBytes_AsString(os2); #endif + /* XXX: logically, there is no problem with an environment + variable having an empty name, but POSIX requires unsetenv() to + refuse to delete such a variable, which can be a problem (on + Linux, for instance, such a variable can be passed to a new + process, but cannot be deleted with unsetenv()). The return + value of unsetenv() is currently not checked (some systems + declare it as void), so an object added to posix_putenv_garbage + for an empty-named variable could be freed while the + environment still pointed into it. */ + if (*s1 == 0) { + PyErr_SetString(PyExc_ValueError, "environment variable name must " + "not be empty"); + goto error; + } + /* An '=' character would be interpreted as the end of the name. */ #ifdef MS_WINDOWS if (wcschr(s1, L'=') != NULL) {