diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d2047d9c2ac..5a0c8a311a7 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -819,9 +819,19 @@ dir_fd_converter(PyObject *o, void *p) } } +#ifdef HAVE_PUTENV +# define PY_PUTENV_DICT +#endif + typedef struct { PyObject *billion; - PyObject *posix_putenv_garbage; +#ifdef PY_PUTENV_DICT + /* putenv() and _wputenv() requires that the caller manages the environment + variable memory. Use a Python dictionary for that: name => env, where + env is a string like "name=value". On Windows, dict keys and values are + Unicode strings. On Unix, they are bytes strings. */ + PyObject *putenv_dict; +#endif PyObject *DirEntryType; PyObject *ScandirIteratorType; #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) @@ -2105,7 +2115,9 @@ static int _posix_clear(PyObject *module) { Py_CLEAR(_posixstate(module)->billion); - Py_CLEAR(_posixstate(module)->posix_putenv_garbage); +#ifdef PY_PUTENV_DICT + Py_CLEAR(_posixstate(module)->putenv_dict); +#endif Py_CLEAR(_posixstate(module)->DirEntryType); Py_CLEAR(_posixstate(module)->ScandirIteratorType); #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) @@ -2130,7 +2142,9 @@ static int _posix_traverse(PyObject *module, visitproc visit, void *arg) { Py_VISIT(_posixstate(module)->billion); - Py_VISIT(_posixstate(module)->posix_putenv_garbage); +#ifdef PY_PUTENV_DICT + Py_VISIT(_posixstate(module)->putenv_dict); +#endif Py_VISIT(_posixstate(module)->DirEntryType); Py_VISIT(_posixstate(module)->ScandirIteratorType); #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) @@ -10047,23 +10061,26 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, } #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ -#ifdef HAVE_PUTENV +#ifdef PY_PUTENV_DICT static void -posix_putenv_garbage_setitem(PyObject *name, PyObject *value) +posix_putenv_dict_setitem(PyObject *name, PyObject *value) { - /* Install the first arg and newstr in posix_putenv_garbage; + /* Install the first arg and newstr in putenv_dict; * this will cause previous value to be collected. This has to * happen after the real putenv() call because the old value * was still accessible until then. */ - if (PyDict_SetItem(_posixstate_global->posix_putenv_garbage, name, value)) + if (PyDict_SetItem(_posixstate_global->putenv_dict, name, value)) /* really not much we can do; just leak */ PyErr_Clear(); else Py_DECREF(value); } +#endif /* PY_PUTENV_DICT */ +#ifdef HAVE_PUTENV + #ifdef MS_WINDOWS /*[clinic input] os.putenv @@ -10114,7 +10131,7 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) goto error; } - posix_putenv_garbage_setitem(name, unicode); + posix_putenv_dict_setitem(name, unicode); Py_RETURN_NONE; error: @@ -10156,7 +10173,7 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) return posix_error(); } - posix_putenv_garbage_setitem(name, bytes); + posix_putenv_dict_setitem(name, bytes); Py_RETURN_NONE; } #endif /* MS_WINDOWS */ @@ -10189,18 +10206,20 @@ os_unsetenv_impl(PyObject *module, PyObject *name) return PyErr_SetFromWindowsErr(0); } - /* Remove the key from posix_putenv_garbage; +#ifdef PY_PUTENV_DICT + /* Remove the key from putenv_dict; * 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(_posixstate(module)->posix_putenv_garbage, name)) { + if (PyDict_DelItem(_posixstate(module)->putenv_dict, name)) { /* really not much we can do; just leak */ if (!PyErr_ExceptionMatches(PyExc_KeyError)) { return NULL; } PyErr_Clear(); } +#endif Py_RETURN_NONE; } @@ -10230,18 +10249,21 @@ os_unsetenv_impl(PyObject *module, PyObject *name) return posix_error(); #endif - /* Remove the key from posix_putenv_garbage; +#ifdef PY_PUTENV_DICT + /* Remove the key from putenv_dict; * 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(_posixstate(module)->posix_putenv_garbage, name)) { + if (PyDict_DelItem(_posixstate(module)->putenv_dict, name)) { /* really not much we can do; just leak */ if (!PyErr_ExceptionMatches(PyExc_KeyError)) { return NULL; } PyErr_Clear(); } +#endif + Py_RETURN_NONE; } #endif /* HAVE_UNSETENV */ @@ -14538,10 +14560,10 @@ INITFUNC(void) Py_INCREF(PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError); -#ifdef HAVE_PUTENV +#ifdef PY_PUTENV_DICT /* Save putenv() parameters as values here, so we can collect them when they * get re-set with another call for the same key. */ - _posixstate(m)->posix_putenv_garbage = PyDict_New(); + _posixstate(m)->putenv_dict = PyDict_New(); #endif #if defined(HAVE_WAITID) && !defined(__APPLE__)