Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 29b238e

Browse files
committed
Issue #9450: Fix memory leaks in readline.remove/replace_history_entry.
1 parent 38557f2 commit 29b238e

2 files changed

Lines changed: 37 additions & 12 deletions

File tree

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Core and Builtins
2121
Extensions
2222
----------
2323

24+
- Issue #9450: Fix memory leak in readline.replace_history_item and
25+
readline.remove_history_item for readline version >= 5.0.
26+
2427
- Issue #8105: Validate file descriptor passed to mmap.mmap on Windows.
2528

2629
- Issue #8046: Add context manager protocol support and .closed property

Modules/readline.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,38 @@ PyDoc_STRVAR(doc_set_completer_delims,
378378
"set_completer_delims(string) -> None\n\
379379
set the readline word delimiters for tab-completion");
380380

381+
/* _py_free_history_entry: Utility function to free a history entry. */
382+
383+
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0500
384+
385+
/* Readline version >= 5.0 introduced a timestamp field into the history entry
386+
structure; this needs to be freed to avoid a memory leak. This version of
387+
readline also introduced the handy 'free_history_entry' function, which
388+
takes care of the timestamp. */
389+
390+
static void
391+
_py_free_history_entry(HIST_ENTRY *entry)
392+
{
393+
histdata_t data = free_history_entry(entry);
394+
free(data);
395+
}
396+
397+
#else
398+
399+
/* No free_history_entry function; free everything manually. */
400+
401+
static void
402+
_py_free_history_entry(HIST_ENTRY *entry)
403+
{
404+
if (entry->line)
405+
free((void *)entry->line);
406+
if (entry->data)
407+
free(entry->data);
408+
free(entry);
409+
}
410+
411+
#endif
412+
381413
static PyObject *
382414
py_remove_history(PyObject *self, PyObject *args)
383415
{
@@ -399,12 +431,7 @@ py_remove_history(PyObject *self, PyObject *args)
399431
return NULL;
400432
}
401433
/* free memory allocated for the history entry */
402-
if (entry->line)
403-
free(entry->line);
404-
if (entry->data)
405-
free(entry->data);
406-
free(entry);
407-
434+
_py_free_history_entry(entry);
408435
Py_RETURN_NONE;
409436
}
410437

@@ -436,12 +463,7 @@ py_replace_history(PyObject *self, PyObject *args)
436463
return NULL;
437464
}
438465
/* free memory allocated for the old history entry */
439-
if (old_entry->line)
440-
free(old_entry->line);
441-
if (old_entry->data)
442-
free(old_entry->data);
443-
free(old_entry);
444-
466+
_py_free_history_entry(old_entry);
445467
Py_RETURN_NONE;
446468
}
447469

0 commit comments

Comments
 (0)