Index: Doc/library/os.rst =================================================================== --- Doc/library/os.rst (revision 68535) +++ Doc/library/os.rst (working copy) @@ -202,8 +202,9 @@ 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`. Availability: most flavors of - Unix, Windows. + :func:`popen` or :func:`fork` and :func:`execv`. Raises :exc:`ValueError` + if *varname* contains an '=' character. + Availability: most flavors of Unix, Windows. .. note:: @@ -317,7 +318,9 @@ Unset (delete) the environment variable named *varname*. Such changes to the environment affect subprocesses started with :func:`os.system`, :func:`popen` or - :func:`fork` and :func:`execv`. Availability: most flavors of Unix, Windows. + :func:`fork` and :func:`execv`. Raises :exc:`OSError` if *varname* is + invalid, for example if it contains an '=' character. + Availability: most flavors of Unix, Windows. When :func:`unsetenv` is supported, deletion of items in ``os.environ`` is automatically translated into a corresponding call to :func:`unsetenv`; however, Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 68535) +++ Lib/test/test_posix.py (working copy) @@ -215,6 +215,23 @@ self.assertEqual(type(k), str) self.assertEqual(type(v), str) + def test_putenv(self): + if hasattr(posix, 'putenv'): + posix.putenv("TESTTEST", "test") + posix.putenv("TESTTEST", "newvalue") + self.assertRaises(ValueError, posix.putenv, "FOO=BAR", "value") + + def test_unsetenv(self): + if hasattr(posix, 'unsetenv'): + posix.putenv("TESTTEST", "test") + posix.unsetenv("TESTTEST") + posix.unsetenv("TESTTEST") + posix.unsetenv("BLAHBLAH") + posix.unsetenv("BLAHBLAH") + # POSIX requires unsetenv to fail here; the posix module + # originally didn't check the return value. + self.assertRaises(OSError, posix.unsetenv, "BAR=BAZ") + def test_getcwd_long_pathnames(self): if hasattr(posix, 'getcwd'): dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef' Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 68535) +++ Modules/posixmodule.c (working copy) @@ -5174,12 +5174,19 @@ /* len includes space for a trailing \0; the size arg to PyBytes_FromStringAndSize does not count that */ #ifdef MS_WINDOWS - len = wcslen(s1) + wcslen(s2) + 2; - newstr = PyUnicode_FromUnicode(NULL, (int)len - 1); + if (wcschr(s1, L'=') == NULL) { + len = wcslen(s1) + wcslen(s2) + 2; + newstr = PyUnicode_FromUnicode(NULL, (int)len - 1); #else - len = strlen(s1) + strlen(s2) + 2; - newstr = PyBytes_FromStringAndSize(NULL, (int)len - 1); + if (strchr(s1, '=') == NULL) { + len = strlen(s1) + strlen(s2) + 2; + newstr = PyBytes_FromStringAndSize(NULL, (int)len - 1); #endif + } else { + PyErr_SetString(PyExc_ValueError, "environment variable names " + "may not contain the '=' character"); + return NULL; + } if (newstr == NULL) return PyErr_NoMemory(); #ifdef MS_WINDOWS @@ -5233,7 +5240,8 @@ if (!PyArg_ParseTuple(args, "s:unsetenv", &s1)) return NULL; - unsetenv(s1); + if (unsetenv(s1)) + return posix_error(); /* Remove the key from posix_putenv_garbage; * this will cause it to be collected. This has to