Skip to content

Commit bca2b4c

Browse files
fix: eliminate memory leak in readline.c
1 parent 629da5c commit bca2b4c

1 file changed

Lines changed: 34 additions & 22 deletions

File tree

Modules/readline.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,29 +1357,41 @@ setup_readline(readlinestate *mod_state)
13571357
if (using_libedit_emulation)
13581358
rl_initialize();
13591359

1360-
/* Detect if libedit's readline emulation uses 0-based
1361-
* indexing or 1-based indexing.
1362-
*/
1363-
add_history("1");
1364-
if (history_get(1) == NULL) {
1365-
libedit_history_start = 0;
1366-
} else {
1367-
libedit_history_start = 1;
1368-
}
1369-
/* Some libedit implementations use 1 based indexing on
1370-
* replace_history_entry where libreadline uses 0 based.
1371-
* The API our module presents is supposed to be 0 based.
1372-
* It's a mad mad mad mad world.
1373-
*/
1374-
{
1375-
add_history("2");
1376-
HIST_ENTRY *old_entry = replace_history_entry(1, "X", NULL);
1377-
_py_free_history_entry_lock_held(old_entry);
1378-
HIST_ENTRY *item = history_get(libedit_history_start);
1379-
if (item && item->line && strcmp(item->line, "X")) {
1380-
libedit_append_replace_history_offset = 0;
1360+
if (using_libedit_emulation) {
1361+
/* Detect if libedit's readline emulation uses 0-based
1362+
* indexing or 1-based indexing.
1363+
*/
1364+
add_history("1");
1365+
if (history_get(1) == NULL) {
1366+
libedit_history_start = 0;
13811367
} else {
1382-
libedit_append_replace_history_offset = 1;
1368+
libedit_history_start = 1;
1369+
}
1370+
/* Some libedit implementations use 1 based indexing on
1371+
* replace_history_entry where libreadline uses 0 based.
1372+
* The API our module presents is supposed to be 0 based.
1373+
* It's a mad mad mad mad world.
1374+
*/
1375+
{
1376+
add_history("2");
1377+
HIST_ENTRY *old_entry = replace_history_entry(1, "X", NULL);
1378+
_py_free_history_entry_lock_held(old_entry);
1379+
HIST_ENTRY *item = history_get(libedit_history_start);
1380+
if (item && item->line && strcmp(item->line, "X")) {
1381+
libedit_append_replace_history_offset = 0;
1382+
} else {
1383+
libedit_append_replace_history_offset = 1;
1384+
}
1385+
}
1386+
/* Use remove_history instead of clear_history to explicitly free
1387+
* each probe entry: some libedit builds do not free the strdup'd line
1388+
* strings inside clear_history, causing a small leak per process. */
1389+
while (history_length > 0) {
1390+
HIST_ENTRY *entry = remove_history(libedit_history_start);
1391+
if (entry == NULL) {
1392+
break;
1393+
}
1394+
_py_free_history_entry_lock_held(entry);
13831395
}
13841396
}
13851397
clear_history();

0 commit comments

Comments
 (0)