* Fix the refcount leak in _PySequence_BytesToCharpArray from r78946.
* Also fixes a potential extra DECREF of an arg in the error case within _posixsubprocess.fork_exec() by not reusing the process_args variable.
This commit is contained in:
parent
845085703c
commit
68f52178d9
|
@ -172,7 +172,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
|
||||||
PyObject *gc_module = NULL;
|
PyObject *gc_module = NULL;
|
||||||
PyObject *executable_list, *py_close_fds;
|
PyObject *executable_list, *py_close_fds;
|
||||||
PyObject *env_list, *preexec_fn;
|
PyObject *env_list, *preexec_fn;
|
||||||
PyObject *process_args = NULL, *converted_args = NULL;
|
PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
|
||||||
PyObject *preexec_fn_args_tuple = NULL;
|
PyObject *preexec_fn_args_tuple = NULL;
|
||||||
int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
|
int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
|
||||||
int errpipe_read, errpipe_write, close_fds, restore_signals;
|
int errpipe_read, errpipe_write, close_fds, restore_signals;
|
||||||
|
@ -224,15 +224,17 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
|
||||||
/* These conversions are done in the parent process to avoid allocating
|
/* These conversions are done in the parent process to avoid allocating
|
||||||
or freeing memory in the child process. */
|
or freeing memory in the child process. */
|
||||||
if (process_args != Py_None) {
|
if (process_args != Py_None) {
|
||||||
|
Py_ssize_t num_args;
|
||||||
/* Equivalent to: */
|
/* Equivalent to: */
|
||||||
/* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
|
/* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */
|
||||||
process_args = PySequence_Fast(process_args, "argv must be a tuple");
|
fast_args = PySequence_Fast(process_args, "argv must be a tuple");
|
||||||
converted_args = PyTuple_New(PySequence_Size(process_args));
|
num_args = PySequence_Fast_GET_SIZE(fast_args);
|
||||||
|
converted_args = PyTuple_New(num_args);
|
||||||
if (converted_args == NULL)
|
if (converted_args == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
for (arg_num = 0; arg_num < PySequence_Size(process_args); ++arg_num) {
|
for (arg_num = 0; arg_num < num_args; ++arg_num) {
|
||||||
PyObject *borrowed_arg, *converted_arg;
|
PyObject *borrowed_arg, *converted_arg;
|
||||||
borrowed_arg = PySequence_Fast_GET_ITEM(process_args, arg_num);
|
borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
|
||||||
if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
|
if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
|
PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
|
||||||
|
@ -240,7 +242,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
|
||||||
|
|
||||||
argv = _PySequence_BytesToCharpArray(converted_args);
|
argv = _PySequence_BytesToCharpArray(converted_args);
|
||||||
Py_CLEAR(converted_args);
|
Py_CLEAR(converted_args);
|
||||||
Py_CLEAR(process_args);
|
Py_CLEAR(fast_args);
|
||||||
if (!argv)
|
if (!argv)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +321,7 @@ cleanup:
|
||||||
_Py_FreeCharPArray(argv);
|
_Py_FreeCharPArray(argv);
|
||||||
_Py_FreeCharPArray(exec_array);
|
_Py_FreeCharPArray(exec_array);
|
||||||
Py_XDECREF(converted_args);
|
Py_XDECREF(converted_args);
|
||||||
Py_XDECREF(process_args);
|
Py_XDECREF(fast_args);
|
||||||
|
|
||||||
/* Reenable gc if it was disabled. */
|
/* Reenable gc if it was disabled. */
|
||||||
if (need_to_reenable_gc)
|
if (need_to_reenable_gc)
|
||||||
|
|
|
@ -2737,6 +2737,7 @@ _PySequence_BytesToCharpArray(PyObject* self)
|
||||||
{
|
{
|
||||||
char **array;
|
char **array;
|
||||||
Py_ssize_t i, argc;
|
Py_ssize_t i, argc;
|
||||||
|
PyObject *item = NULL;
|
||||||
|
|
||||||
argc = PySequence_Size(self);
|
argc = PySequence_Size(self);
|
||||||
if (argc == -1)
|
if (argc == -1)
|
||||||
|
@ -2749,7 +2750,7 @@ _PySequence_BytesToCharpArray(PyObject* self)
|
||||||
}
|
}
|
||||||
for (i = 0; i < argc; ++i) {
|
for (i = 0; i < argc; ++i) {
|
||||||
char *data;
|
char *data;
|
||||||
PyObject *item = PySequence_GetItem(self, i);
|
item = PySequence_GetItem(self, i);
|
||||||
data = PyBytes_AsString(item);
|
data = PyBytes_AsString(item);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
/* NULL terminate before freeing. */
|
/* NULL terminate before freeing. */
|
||||||
|
@ -2761,12 +2762,14 @@ _PySequence_BytesToCharpArray(PyObject* self)
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(item);
|
||||||
}
|
}
|
||||||
array[argc] = NULL;
|
array[argc] = NULL;
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
Py_XDECREF(item);
|
||||||
_Py_FreeCharPArray(array);
|
_Py_FreeCharPArray(array);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue