summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-06-26 06:30:59 (GMT)
committerGitHub <noreply@github.com>2023-06-26 06:30:59 (GMT)
commit7ca871634e7ae8b9c295df5c2154338d2dac1e69 (patch)
tree815a93f37e38a5fd7fbe2d6c3df11b65364a33ae
parent00e75a33728cdad7c10088acc36bc55b2f4a0efe (diff)
downloadcpython-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.
-rw-r--r--Include/cpython/abstract.h4
-rw-r--r--Modules/_posixsubprocess.c82
-rw-r--r--Objects/abstract.c77
3 files changed, 82 insertions, 81 deletions
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
index abae3e4..5d2d2af 100644
--- a/Include/cpython/abstract.h
+++ b/Include/cpython/abstract.h
@@ -171,10 +171,6 @@ PyAPI_FUNC(int) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls);
PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls);
-PyAPI_FUNC(char *const *) _PySequence_BytesToCharpArray(PyObject* self);
-
-PyAPI_FUNC(void) _Py_FreeCharPArray(char *const array[]);
-
/* For internal use by buffer API functions */
PyAPI_FUNC(void) _Py_add_one_to_index_F(int nd, Py_ssize_t *index,
const Py_ssize_t *shape);
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
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 00087bd..fecdb4e 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2906,80 +2906,3 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
}
return PYGEN_ERROR;
}
-
-/*
- * 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().
- */
-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. */
-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);
-}