diff options
author | Victor Stinner <vstinner@python.org> | 2023-06-26 06:30:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-26 06:30:59 (GMT) |
commit | 7ca871634e7ae8b9c295df5c2154338d2dac1e69 (patch) | |
tree | 815a93f37e38a5fd7fbe2d6c3df11b65364a33ae /Modules | |
parent | 00e75a33728cdad7c10088acc36bc55b2f4a0efe (diff) | |
download | cpython-7ca871634e7ae8b9c295df5c2154338d2dac1e69.zip cpython-7ca871634e7ae8b9c295df5c2154338d2dac1e69.tar.gz cpython-7ca871634e7ae8b9c295df5c2154338d2dac1e69.tar.bz2 |
gh-106084: Remove _PySequence_BytesToCharpArray() function (#106088)
Remove private _PySequence_BytesToCharpArray() and
_Py_FreeCharPArray() functions from the public C API: move these
functions from Objects/abstract.c to Modules/_posixsubprocess.c.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_posixsubprocess.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 2d88f5e..52e1d2f 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -182,6 +182,88 @@ _is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence, return 0; } + +// Forward declaration +static void _Py_FreeCharPArray(char *const array[]); + +/* + * Flatten a sequence of bytes() objects into a C array of + * NULL terminated string pointers with a NULL char* terminating the array. + * (ie: an argv or env list) + * + * Memory allocated for the returned list is allocated using PyMem_Malloc() + * and MUST be freed by _Py_FreeCharPArray(). + */ +static char *const * +_PySequence_BytesToCharpArray(PyObject* self) +{ + char **array; + Py_ssize_t i, argc; + PyObject *item = NULL; + Py_ssize_t size; + + argc = PySequence_Size(self); + if (argc == -1) + return NULL; + + assert(argc >= 0); + + if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) { + PyErr_NoMemory(); + return NULL; + } + + array = PyMem_Malloc((argc + 1) * sizeof(char *)); + if (array == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < argc; ++i) { + char *data; + item = PySequence_GetItem(self, i); + if (item == NULL) { + /* NULL terminate before freeing. */ + array[i] = NULL; + goto fail; + } + /* check for embedded null bytes */ + if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) { + /* NULL terminate before freeing. */ + array[i] = NULL; + goto fail; + } + size = PyBytes_GET_SIZE(item) + 1; + array[i] = PyMem_Malloc(size); + if (!array[i]) { + PyErr_NoMemory(); + goto fail; + } + memcpy(array[i], data, size); + Py_DECREF(item); + } + array[argc] = NULL; + + return array; + +fail: + Py_XDECREF(item); + _Py_FreeCharPArray(array); + return NULL; +} + + +/* Free's a NULL terminated char** array of C strings. */ +static void +_Py_FreeCharPArray(char *const array[]) +{ + Py_ssize_t i; + for (i = 0; array[i] != NULL; ++i) { + PyMem_Free(array[i]); + } + PyMem_Free((void*)array); +} + + /* * Do all the Python C API calls in the parent process to turn the pass_fds * "py_fds_to_keep" tuple into a C array. The caller owns allocation and |