* 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:
Gregory P. Smith 2010-03-15 06:07:42 +00:00
parent 845085703c
commit 68f52178d9
2 changed files with 13 additions and 8 deletions

View File

@ -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)

View File

@ -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;
} }