Skip to content

bpo-33630: Fix memory leak in old versions of glicb for posix_spawn. #7685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 19, 2018
25 changes: 22 additions & 3 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -5179,7 +5179,8 @@ enum posix_spawn_file_actions_identifier {

static int
parse_file_actions(PyObject *file_actions,
posix_spawn_file_actions_t *file_actionsp)
posix_spawn_file_actions_t *file_actionsp,
PyObject *temp_buffer)
{
PyObject *seq;
PyObject *file_action = NULL;
Expand Down Expand Up @@ -5224,9 +5225,13 @@ parse_file_actions(PyObject *file_actions,
{
goto fail;
}
if (PyList_Append(temp_buffer, path)) {
Py_DECREF(path);
goto fail;
}
errno = posix_spawn_file_actions_addopen(file_actionsp,
fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
Py_DECREF(path); /* addopen copied it. */
Py_DECREF(path);
if (errno) {
posix_error();
goto fail;
Expand Down Expand Up @@ -5309,6 +5314,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
posix_spawn_file_actions_t *file_actionsp = NULL;
Py_ssize_t argc, envc;
PyObject *result = NULL;
PyObject *temp_buffer = NULL;
pid_t pid;
int err_code;

Expand Down Expand Up @@ -5349,7 +5355,19 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
}

if (file_actions != Py_None) {
if (parse_file_actions(file_actions, &file_actions_buf)) {
/* There is a bug in old versions of glibc that makes some of the
* helper functions for manipulating file actions not copy the provided
* buffers. The problem is that posix_spawn_file_actions_addopen does not
* copy the value of path for some old versions of glibc (<2.20).
* The use of temp_buffer here is a workaround that keeps the
* python objects that own the buffers alive until posix_spawn gets called.
* Check https://bugs.python.org/issue33630 and
* https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
temp_buffer = PyList_New(0);
if (!temp_buffer) {
goto exit;
}
if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
goto exit;
}
file_actionsp = &file_actions_buf;
Expand All @@ -5376,6 +5394,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
if (argvlist) {
free_string_array(argvlist, argc);
}
Py_XDECREF(temp_buffer);
return result;
}
#endif /* HAVE_POSIX_SPAWN */
Expand Down