8000 gh-106084: Remove _PySequence_BytesToCharpArray() function · vstinner/cpython@62a11ff · GitHub
[go: up one dir, main page]

Skip to content

Commit 62a11ff

Browse files
committed
pythongh-106084: Remove _PySequence_BytesToCharpArray() function
Remove private _PySequence_BytesToCharpArray() and _Py_FreeCharPArray() functions from the public C API: move these functions from Objects/abstract.c to Modules/_posixsubprocess.c.
1 parent 8c24a83 commit 62a11ff

File tree

3 files changed

+79
-81
lines changed

3 files changed

+79
-81
lines changed

Include/cpython/abstract.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,6 @@ PyAPI_FUNC(int) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls);
180180

181181
PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls);
182182

183-
PyAPI_FUNC(char *const *) _PySequence_BytesToCharpArray(PyObject* self);
184-
185-
PyAPI_FUNC(void) _Py_FreeCharPArray(char *const array[]);
186-
187183
/* For internal use by buffer API functions */
188184
PyAPI_FUNC(void) _Py_add_one_to_index_F(int nd, Py_ssize_t *index,
189185
const Py_ssize_t *shape);

Modules/_posixsubprocess.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,85 @@ _is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence,
182182
return 0;
183183
}
184184

185+
186+
/*
187+
* Flatten a sequence of bytes() objects into a C array of
188+
* NULL terminated string pointers with a NULL char* terminating the array.
189+
* (ie: an argv or env list)
190+
*
191+
* Memory allocated for the returned list is allocated using PyMem_Malloc()
192+
* and MUST be freed by _Py_FreeCharPArray().
193+
*/
194+
static char *const *
195+
_PySequence_BytesToCharpArray(PyObject* self)
196+
{
197+
char **array;
198+
Py_ssize_t i, argc;
199+
PyObject *item = NULL;
200+
Py_ssize_t size;
201+
202+
argc = PySequence_Size(self);
203+
if (argc == -1)
204+
return NULL;
205+
206+
assert(argc >= 0);
207+
208+
if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) {
209+
PyErr_NoMemory();
210+
return NULL;
211+
}
212+
213+
array = PyMem_Malloc((argc + 1) * sizeof(char *));
214+
if (array == NULL) {
215+
PyErr_NoMemory();
216+
return NULL;
217+
}
218+
for (i = 0; i < argc; ++i) {
219+
char *data;
220+
item = PySequence_GetItem(self, i);
221+
if (item == NULL) {
222+
/* NULL terminate before freeing. */
223+
array[i] = NULL;
224+
goto fail;
225+
}
226+
/* check for embedded null bytes */
227+
if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) {
228+
/* NULL terminate before freeing. */
229+
array[i] = NULL;
230+
goto fail;
231+
}
232+
size = PyBytes_GET_SIZE(item) + 1;
233+
array[i] = PyMem_Malloc(size);
234+
if (!array[i]) {
235+
PyErr_NoMemory();
236+
goto fail;
237+
}
238+
memcpy(array[i], data, size);
239+
Py_DECREF(item);
240+
}
241+
array[argc] = NULL;
242+
243+
return array;
244+
245+
fail:
246+
Py_XDECREF(item);
247+
_Py_FreeCharPArray(array);
248+
return NULL;
249+
}
250+
251+
252+
/* Free's a NULL terminated char** array of C strings. */
253+
static void
254+
_Py_FreeCharPArray(char *const array[])
255+
{
256+
Py_ssize_t i;
257+
for (i = 0; array[i] != NULL; ++i) {
258+
PyMem_Free(array[i]);
259+
}
260+
PyMem_Free((void*)array);
261+
}
262+
263+
185264
/*
186265
* Do all the Python C API calls in the parent process to turn the pass_fds
187266
* "py_fds_to_keep" tuple into a C array. The caller owns allocation and

Objects/abstract.c

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,80 +2906,3 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result)
29062906
}
29072907
return PYGEN_ERROR;
29082908
}
2909-
2910-
/*
2911-
* Flatten a sequence of bytes() objects into a C array of
2912-
* NULL terminated string pointers with a NULL char* terminating the array.
2913-
* (ie: an argv or env list)
2914-
*
2915-
* Memory allocated for the returned list is allocated using PyMem_Malloc()
2916-
* and MUST be freed by _Py_FreeCharPArray().
2917-
*/
2918-
char *const *
2919-
_PySequence_BytesToCharpArray(PyObject* self)
2920-
{
2921-
char **array;
2922-
Py_ssize_t i, argc;
2923-
PyObject *item = NULL;
2924-
Py_ssize_t size;
2925-
2926-
argc = PySequence_Size(self);
2927-
if (argc == -1)
2928-
return NULL;
2929-
2930-
assert(argc >= 0);
2931-
2932-
if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) {
2933-
PyErr_NoMemory();
2934-
return NULL;
2935-
}
2936-
2937-
array = PyMem_Malloc((argc + 1) * sizeof(char *));
2938-
if (array == NULL) {
2939-
PyErr_NoMemory();
2940-
return NULL;
2941-
}
2942-
for (i = 0; i < argc; ++i) {
2943-
char *data;
2944-
item = PySequence_GetItem(self, i);
2945-
if (item == NULL) {
2946-
/* NULL terminate before freeing. */
2947-
array[i] = NULL;
2948-
goto fail;
2949-
}
2950-
/* check for embedded null bytes */
2951-
if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) {
2952-
/* NULL terminate before freeing. */
2953-
array[i] = NULL;
2954-
goto fail;
2955-
}
2956-
size = PyBytes_GET_SIZE(item) + 1;
2957-
array[i] = PyMem_Malloc(size);
2958-
if (!array[i]) {
2959-
PyErr_NoMemory();
2960-
goto fail;
2961-
}
2962-
memcpy(array[i], data, size);
2963-
Py_DECREF(item);
2964-
}
2965-
array[argc] = NULL;
2966-
2967-
return array;
2968-
2969-
fail:
2970-
Py_XDECREF(item);
2971-
_Py_FreeCharPArray(array);
2972-
return NULL;
2973-
}
2974-
2975-
2976-
/* Free's a NULL terminated char** array of C strings. */
2977-
void
2978-
_Py_FreeCharPArray(char *const array[])
2979-
{
2980-
Py_ssize_t i;
2981-
for (i = 0; array[i] != NULL; ++i) {
2982-
PyMem_Free(array[i]);
2983-
}
2984-
PyMem_Free((void*)array);
2985-
}

0 commit comments

Comments
 (0)
0