Make posix.putenv() raise ValueError if name contains an '=' character. diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -253,7 +253,8 @@ process and user. Set the environment variable named *varname* to the string *value*. Such changes to the environment affect subprocesses started with :func:`os.system`, - :func:`popen` or :func:`fork` and :func:`execv`. + :func:`popen` or :func:`fork` and :func:`execv`. Raises :exc:`ValueError` + if *varname* 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 @@ -345,6 +345,14 @@ class EnvironTests(mapping_tests.BasicTe value = os.popen("/bin/sh -c 'echo $HELLO'").read().strip() self.assertEquals(value, "World") + def test_bad_keys(self): + # Issue #4926 + os.environ.clear() + self.assertRaises(ValueError, os.environ.__setitem__, + "PYTHONTESTVAROS=SOMETHING", "value") + self.assertTrue("PYTHONTESTVAROS=SOMETHING" not in os.environ) + self.assertTrue("PYTHONTESTVAROS" not in os.environ) + class WalkTests(unittest.TestCase): """Tests for os.walk().""" 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 @@ -320,6 +320,27 @@ class PosixTester(unittest.TestCase): if hasattr(st, 'st_flags'): posix.lchflags(test_support.TESTFN, st.st_flags) + def test_putenv(self): + if not hasattr(posix, 'putenv'): + return + # XXX: we can't read the values back, as there's no wrapper + # for getenv() - os.getenv() reads the value out of + # os.environ, which, like posix.environ, doesn't reflect + # changes made with putenv() or unsetenv(). + try: + posix.putenv("PYTHONTESTVARA", "value1") + posix.putenv("PYTHONTESTVARA", "value2") + if hasattr(posix, 'unsetenv'): + posix.unsetenv("PYTHONTESTVARA") + posix.putenv("PYTHONTESTVARA", "value3") + posix.putenv("PYTHONTESTVARA", "value4") + finally: + if hasattr(posix, 'unsetenv'): + posix.unsetenv("PYTHONTESTVARA") + # See issue #4926 + self.assertRaises(ValueError, posix.putenv, + "PYTHONTESTVARB=SOMETHING", "value") + def test_getcwd_long_pathnames(self): if hasattr(posix, 'getcwd'): dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef' diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6868,6 +6868,13 @@ posix_putenv(PyObject *self, PyObject *a if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2)) return NULL; + /* An '=' character would be interpreted as the end of the name. */ + if (strchr(s1, '=') != NULL) { + PyErr_SetString(PyExc_ValueError, "environment variable name must " + "not contain the '=' character"); + return NULL; + } + #if defined(PYOS_OS2) if (stricmp(s1, "BEGINLIBPATH") == 0) { APIRET rc;