Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix :c:func:`PyInitConfig_GetStrList` and :c:func:`PyInitConfig_SetStrList`
for empty string lists on platforms where ``malloc(0)`` returns ``NULL``.
Previously these APIs could spuriously report out-of-memory for a valid
empty list.
10 changes: 10 additions & 0 deletions Programs/_testembed.c
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,8 @@ static int test_initconfig_get_api(void)
char **items;
assert(PyInitConfig_GetStrList(config, "xoptions", &length, &items) == 0);
assert(length == 0);
assert(items == NULL);
PyInitConfig_FreeStrList(length, items);

char* xoptions[] = {"faulthandler"};
assert(PyInitConfig_SetStrList(config, "xoptions",
Expand All @@ -1882,6 +1884,14 @@ static int test_initconfig_get_api(void)
assert(strcmp(items[0], "faulthandler") == 0);
PyInitConfig_FreeStrList(length, items);

// Setting an empty list must succeed even on platforms where malloc(0)
// returns NULL, and must round-trip through GetStrList().
assert(PyInitConfig_SetStrList(config, "xoptions", 0, NULL) == 0);
assert(PyInitConfig_GetStrList(config, "xoptions", &length, &items) == 0);
assert(length == 0);
assert(items == NULL);
PyInitConfig_FreeStrList(length, items);

// Setting hash_seed sets use_hash_seed
assert(initconfig_getint(config, "use_hash_seed") == 0);
assert(PyInitConfig_SetInt(config, "hash_seed", 123) == 0);
Expand Down
14 changes: 14 additions & 0 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -4213,6 +4213,12 @@ PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length,
PyWideStringList *list = raw_member;
*length = list->length;

// Don't call malloc(0): it may return NULL on some platforms.
if (list->length == 0) {
*items = NULL;
return 0;
}

*items = malloc(list->length * sizeof(char*));
if (*items == NULL) {
config->status = _PyStatus_NO_MEMORY();
Expand Down Expand Up @@ -4408,6 +4414,14 @@ initconfig_set_str_list(PyInitConfig *config, PyWideStringList *list,
Py_ssize_t length, char * const *items)
{
PyWideStringList wlist = _PyWideStringList_INIT;

// Don't call malloc(0): it may return NULL on some platforms.
if (length == 0) {
initconfig_free_wstr_list(list);
*list = wlist;
return 0;
}

size_t size = sizeof(wchar_t*) * length;
wlist.items = (wchar_t **)malloc(size);
if (wlist.items == NULL) {
Expand Down
Loading