Skip to content

Commit 96dee64

Browse files
authored
gh-138756: Fix memory leak in PyInitConfig_Free() (#138759)
Clear also memory of PyConfig members.
1 parent 1011724 commit 96dee64

File tree

1 file changed

+51
-9
lines changed

1 file changed

+51
-9
lines changed

Python/initconfig.c

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,11 @@ static const PyConfigSpec PYPRECONFIG_SPEC[] = {
239239

240240

241241
// Forward declarations
242-
static PyObject*
243-
config_get(const PyConfig *config, const PyConfigSpec *spec,
244-
int use_sys);
242+
static PyObject* config_get(const PyConfig *config, const PyConfigSpec *spec,
243+
int use_sys);
244+
static void initconfig_free_wstr(wchar_t *member);
245+
static void initconfig_free_wstr_list(PyWideStringList *list);
246+
static void initconfig_free_config(const PyConfig *config);
245247

246248

247249
/* --- Command line options --------------------------------------- */
@@ -3725,6 +3727,8 @@ PyInitConfig_Free(PyInitConfig *config)
37253727
if (config == NULL) {
37263728
return;
37273729
}
3730+
3731+
initconfig_free_config(&config->config);
37283732
free(config->err_msg);
37293733
free(config);
37303734
}
@@ -4093,13 +4097,51 @@ PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char* value)
40934097
}
40944098

40954099

4100+
static void
4101+
initconfig_free_wstr(wchar_t *member)
4102+
{
4103+
if (member) {
4104+
free(member);
4105+
}
4106+
}
4107+
4108+
4109+
static void
4110+
initconfig_free_wstr_list(PyWideStringList *list)
4111+
{
4112+
for (Py_ssize_t i = 0; i < list->length; i++) {
4113+
free(list->items[i]);
4114+
}
4115+
free(list->items);
4116+
}
4117+
4118+
4119+
static void
4120+
initconfig_free_config(const PyConfig *config)
4121+
{
4122+
const PyConfigSpec *spec = PYCONFIG_SPEC;
4123+
for (; spec->name != NULL; spec++) {
4124+
void *member = config_get_spec_member(config, spec);
4125+
if (spec->type == PyConfig_MEMBER_WSTR
4126+
|| spec->type == PyConfig_MEMBER_WSTR_OPT)
4127+
{
4128+
wchar_t *wstr = *(wchar_t **)member;
4129+
initconfig_free_wstr(wstr);
4130+
}
4131+
else if (spec->type == PyConfig_MEMBER_WSTR_LIST) {
4132+
initconfig_free_wstr_list(member);
4133+
}
4134+
}
4135+
}
4136+
4137+
40964138
static int
4097-
_PyWideStringList_FromUTF8(PyInitConfig *config, PyWideStringList *list,
4098-
Py_ssize_t length, char * const *items)
4139+
initconfig_set_str_list(PyInitConfig *config, PyWideStringList *list,
4140+
Py_ssize_t length, char * const *items)
40994141
{
41004142
PyWideStringList wlist = _PyWideStringList_INIT;
41014143
size_t size = sizeof(wchar_t*) * length;
4102-
wlist.items = (wchar_t **)PyMem_RawMalloc(size);
4144+
wlist.items = (wchar_t **)malloc(size);
41034145
if (wlist.items == NULL) {
41044146
config->status = _PyStatus_NO_MEMORY();
41054147
return -1;
@@ -4108,14 +4150,14 @@ _PyWideStringList_FromUTF8(PyInitConfig *config, PyWideStringList *list,
41084150
for (Py_ssize_t i = 0; i < length; i++) {
41094151
wchar_t *arg = utf8_to_wstr(config, items[i]);
41104152
if (arg == NULL) {
4111-
_PyWideStringList_Clear(&wlist);
4153+
initconfig_free_wstr_list(&wlist);
41124154
return -1;
41134155
}
41144156
wlist.items[i] = arg;
41154157
wlist.length++;
41164158
}
41174159

4118-
_PyWideStringList_Clear(list);
4160+
initconfig_free_wstr_list(list);
41194161
*list = wlist;
41204162
return 0;
41214163
}
@@ -4136,7 +4178,7 @@ PyInitConfig_SetStrList(PyInitConfig *config, const char *name,
41364178
return -1;
41374179
}
41384180
PyWideStringList *list = raw_member;
4139-
if (_PyWideStringList_FromUTF8(config, list, length, items) < 0) {
4181+
if (initconfig_set_str_list(config, list, length, items) < 0) {
41404182
return -1;
41414183
}
41424184

0 commit comments

Comments
 (0)