diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index efa28ea952b..d06f08ed843 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -423,6 +423,15 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol): value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape') self.assertEqual(os.environ['bytes'], value_str) + def test_unset_error(self): + if sys.platform == "win32": + # an environment variable is limited to 32,767 characters + key = 'x' * 50000 + else: + # "=" is not allowed in a variable name + key = 'key=' + self.assertRaises(OSError, os.environ.__delitem__, key) + class WalkTests(unittest.TestCase): """Tests for os.walk().""" diff --git a/Misc/NEWS b/Misc/NEWS index 0b228ef14bc..63508182750 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -83,6 +83,8 @@ Core and Builtins Library ------- +- Issue #13415: os.unsetenv() doesn't ignore errors anymore. + - Issue #13322: Fix BufferedWriter.write() to ensure that BlockingIOError is raised when the wrapped raw file is non-blocking and the write would block. Previous code assumed that the raw write() would raise BlockingIOError, but diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a27ac7111dc..728644534d4 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6106,6 +6106,12 @@ posix_putenv(PyObject *self, PyObject *args) PyBytes_FromStringAndSize does not count that */ #ifdef MS_WINDOWS len = wcslen(s1) + wcslen(s2) + 2; + if (_MAX_ENV < (len - 1)) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + goto error; + } newstr = PyUnicode_FromUnicode(NULL, (int)len - 1); #else len = PyBytes_GET_SIZE(os1) + PyBytes_GET_SIZE(os2) + 2; @@ -6177,42 +6183,30 @@ Delete an environment variable."); static PyObject * posix_unsetenv(PyObject *self, PyObject *args) { -#ifdef MS_WINDOWS - char *s1; - - if (!PyArg_ParseTuple(args, "s:unsetenv", &s1)) - return NULL; -#else PyObject *os1; char *s1; + int err; if (!PyArg_ParseTuple(args, "O&:unsetenv", PyUnicode_FSConverter, &os1)) return NULL; s1 = PyBytes_AsString(os1); -#endif - unsetenv(s1); + err = unsetenv(s1); + if (err) + return posix_error(); /* Remove the key from posix_putenv_garbage; * this will cause it to be collected. This has to * happen after the real unsetenv() call because the * old value was still accessible until then. */ - if (PyDict_DelItem(posix_putenv_garbage, -#ifdef MS_WINDOWS - PyTuple_GET_ITEM(args, 0) -#else - os1 -#endif - )) { + if (PyDict_DelItem(posix_putenv_garbage, os1)) { /* really not much we can do; just leak */ PyErr_Clear(); } -#ifndef MS_WINDOWS Py_DECREF(os1); -#endif Py_RETURN_NONE; } #endif /* unsetenv */