8000 gh-106084: Remove _PySequence_BytesToCharpArray() function (#106088) · python/cpython@7ca8716 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ca8716

Browse files
authored
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.
1 parent 00e75a3 commit 7ca8716

File tree

3 files changed

+82
-81
lines changed
Filter options

3 files changed

+82
-81
lines changed

Include/cpython/abstract.h

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

172172
PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls);
173173

174-
PyAPI_FUNC(char *const *) _PySequence_BytesToCharpArray(PyObject* self);
175-
176-
PyAPI_FUNC(void) _Py_FreeCharPArray(char *const array[]);
177-
178174
/* For internal use by buffer API functions */
179175
PyAPI_FUNC(void) _Py_add_one_to_index_F(int nd, Py_ssize_t *index,
180176
const Py_ssize_t *shape);

Modules/_posixsubprocess.c

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

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