[3.14] gh-138756: Fix memory leak in PyInitConfig_Free() (GH-138759) (#138785)

gh-138756: Fix memory leak in PyInitConfig_Free() (GH-138759)

Clear also memory of PyConfig members.
(cherry picked from commit 96dee64c73)

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Miss Islington (bot) 2025-10-07 18:42:50 +02:00 committed by GitHub
parent 6ed9be1a55
commit 0accda7468
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -239,9 +239,11 @@ static const PyConfigSpec PYPRECONFIG_SPEC[] = {
// Forward declarations
static PyObject*
config_get(const PyConfig *config, const PyConfigSpec *spec,
int use_sys);
static PyObject* config_get(const PyConfig *config, const PyConfigSpec *spec,
int use_sys);
static void initconfig_free_wstr(wchar_t *member);
static void initconfig_free_wstr_list(PyWideStringList *list);
static void initconfig_free_config(const PyConfig *config);
/* --- Command line options --------------------------------------- */
@ -3725,6 +3727,8 @@ PyInitConfig_Free(PyInitConfig *config)
if (config == NULL) {
return;
}
initconfig_free_config(&config->config);
free(config->err_msg);
free(config);
}
@ -4093,13 +4097,51 @@ PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char* value)
}
static void
initconfig_free_wstr(wchar_t *member)
{
if (member) {
free(member);
}
}
static void
initconfig_free_wstr_list(PyWideStringList *list)
{
for (Py_ssize_t i = 0; i < list->length; i++) {
free(list->items[i]);
}
free(list->items);
}
static void
initconfig_free_config(const PyConfig *config)
{
const PyConfigSpec *spec = PYCONFIG_SPEC;
for (; spec->name != NULL; spec++) {
void *member = config_get_spec_member(config, spec);
if (spec->type == PyConfig_MEMBER_WSTR
|| spec->type == PyConfig_MEMBER_WSTR_OPT)
{
wchar_t *wstr = *(wchar_t **)member;
initconfig_free_wstr(wstr);
}
else if (spec->type == PyConfig_MEMBER_WSTR_LIST) {
initconfig_free_wstr_list(member);
}
}
}
static int
_PyWideStringList_FromUTF8(PyInitConfig *config, PyWideStringList *list,
Py_ssize_t length, char * const *items)
initconfig_set_str_list(PyInitConfig *config, PyWideStringList *list,
Py_ssize_t length, char * const *items)
{
PyWideStringList wlist = _PyWideStringList_INIT;
size_t size = sizeof(wchar_t*) * length;
wlist.items = (wchar_t **)PyMem_RawMalloc(size);
wlist.items = (wchar_t **)malloc(size);
if (wlist.items == NULL) {
config->status = _PyStatus_NO_MEMORY();
return -1;
@ -4108,14 +4150,14 @@ _PyWideStringList_FromUTF8(PyInitConfig *config, PyWideStringList *list,
for (Py_ssize_t i = 0; i < length; i++) {
wchar_t *arg = utf8_to_wstr(config, items[i]);
if (arg == NULL) {
_PyWideStringList_Clear(&wlist);
initconfig_free_wstr_list(&wlist);
return -1;
}
wlist.items[i] = arg;
wlist.length++;
}
_PyWideStringList_Clear(list);
initconfig_free_wstr_list(list);
*list = wlist;
return 0;
}
@ -4136,7 +4178,7 @@ PyInitConfig_SetStrList(PyInitConfig *config, const char *name,
return -1;
}
PyWideStringList *list = raw_member;
if (_PyWideStringList_FromUTF8(config, list, length, items) < 0) {
if (initconfig_set_str_list(config, list, length, items) < 0) {
return -1;
}