diff options
author | Fred Drake <fdrake@acm.org> | 1999-08-26 17:23:54 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 1999-08-26 17:23:54 (GMT) |
commit | 762e206706b5fbf4d541006b8f2b0ca17cac6240 (patch) | |
tree | 2b3239b2ee32d813a79286408db50039739da59f | |
parent | e7f19200e8202275ea5677f61853da448b0ca7cd (diff) | |
download | cpython-762e206706b5fbf4d541006b8f2b0ca17cac6240.zip cpython-762e206706b5fbf4d541006b8f2b0ca17cac6240.tar.gz cpython-762e206706b5fbf4d541006b8f2b0ca17cac6240.tar.bz2 |
posix_putenv(): Constrain memory leakage when setting the same
environment variable repeatedly. I posted this to the list
some time ago, but only now got around to asking g--d- what he
thought about it.
-rw-r--r-- | Modules/posixmodule.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 947e169..61c9a21 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2787,6 +2787,10 @@ Change or add an environment variable."; int putenv( const char *str ); #endif +/* Save putenv() parameters as values here, so we can collect them when they + * get re-set with another call for the same key. */ +static PyObject *posix_putenv_garbage; + static PyObject * posix_putenv(self, args) PyObject *self; @@ -2794,6 +2798,7 @@ posix_putenv(self, args) { char *s1, *s2; char *new; + PyObject *newstr; if (!PyArg_ParseTuple(args, "ss", &s1, &s2)) return NULL; @@ -2821,14 +2826,28 @@ posix_putenv(self, args) } else { #endif - /* XXX This leaks memory -- not easy to fix :-( */ - if ((new = malloc(strlen(s1) + strlen(s2) + 2)) == NULL) - return PyErr_NoMemory(); + /* XXX This can leak memory -- not easy to fix :-( */ + newstr = PyString_FromStringAndSize(NULL, strlen(s1) + strlen(s2) + 2); + if (newstr == NULL) + return PyErr_NoMemory(); + new = PyString_AS_STRING(newstr); (void) sprintf(new, "%s=%s", s1, s2); if (putenv(new)) { posix_error(); return NULL; } + /* Install the first arg and newstr in posix_putenv_garbage; + * 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(posix_putenv_garbage, + PyTuple_GET_ITEM(args, 0), newstr)) { + /* really not much we can do; just leak */ + PyErr_Clear(); + } + else { + Py_DECREF(newstr); + } #if defined(PYOS_OS2) } @@ -3500,4 +3519,6 @@ INITFUNC() return; PyDict_SetItemString(d, "error", PyExc_OSError); + + posix_putenv_garbage = PyDict_New(); } |