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

Skip to content

Commit 6b54e1f

Browse files
committed
Issue #8065: Fix another memory leak in readline module, from failure to free
the result of a call to history_get_history_state.
1 parent 29b238e commit 6b54e1f

2 files changed

Lines changed: 29 additions & 19 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 #8065: Fix memory leak in readline module (from failure to
25+
free the result of history_get_history_state()).
26+
2427
- Issue #9450: Fix memory leak in readline.replace_history_item and
2528
readline.remove_history_item for readline version >= 5.0.
2629

Modules/readline.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,25 @@ PyDoc_STRVAR(doc_get_completer,
534534
\n\
535535
Returns current completer function.");
536536

537+
/* Private function to get current length of history. XXX It may be
538+
* possible to replace this with a direct use of history_length instead,
539+
* but it's not clear whether BSD's libedit keeps history_length up to date.
540+
* See issue #8065.*/
541+
542+
static int
543+
_py_get_history_length(void)
544+
{
545+
HISTORY_STATE *hist_st = history_get_history_state();
546+
int length = hist_st->length;
547+
/* the history docs don't say so, but the address of hist_st changes each
548+
time history_get_history_state is called which makes me think it's
549+
freshly malloc'd memory... on the other hand, the address of the last
550+
line stays the same as long as history isn't extended, so it appears to
551+
be malloc'd but managed by the history package... */
552+
free(hist_st);
553+
return length;
554+
}
555+
537556
/* Exported function to get any element of history */
538557

539558
static PyObject *
@@ -552,17 +571,15 @@ get_history_item(PyObject *self, PyObject *args)
552571
* code doesn't have to worry about the
553572
* difference.
554573
*/
555-
HISTORY_STATE *hist_st;
556-
hist_st = history_get_history_state();
557-
574+
int length = _py_get_history_length();
558575
idx --;
559576

560577
/*
561578
* Apple's readline emulation crashes when
562579
* the index is out of range, therefore
563580
* test for that and fail gracefully.
564581
*/
565-
if (idx < 0 || idx >= hist_st->length) {
582+
if (idx < 0 || idx >= length) {
566583
Py_RETURN_NONE;
567584
}
568585
}
@@ -584,10 +601,7 @@ return the current contents of history item at index.");
584601
static PyObject *
585602
get_current_history_length(PyObject *self, PyObject *noarg)
586603
{
587-
HISTORY_STATE *hist_st;
588-
589-
hist_st = history_get_history_state();
590-
return PyLong_FromLong(hist_st ? (long) hist_st->length : (long) 0);
604+
return PyLong_FromLong((long)_py_get_history_length());
591605
}
592606

593607
PyDoc_STRVAR(doc_get_current_history_length,
@@ -1067,29 +1081,22 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
10671081
n = strlen(p);
10681082
if (n > 0) {
10691083
char *line;
1070-
HISTORY_STATE *state = history_get_history_state();
1071-
if (state->length > 0)
1084+
int length = _py_get_history_length();
1085+
if (length > 0)
10721086
#ifdef __APPLE__
10731087
if (using_libedit_emulation) {
10741088
/*
10751089
* Libedit's emulation uses 0-based indexes,
10761090
* the real readline uses 1-based indexes.
10771091
*/
1078-
line = history_get(state->length - 1)->line;
1092+
line = history_get(length - 1)->line;
10791093
} else
10801094
#endif /* __APPLE__ */
1081-
line = history_get(state->length)->line;
1095+
line = history_get(length)->line;
10821096
else
10831097
line = "";
10841098
if (strcmp(p, line))
10851099
add_history(p);
1086-
/* the history docs don't say so, but the address of state
1087-
changes each time history_get_history_state is called
1088-
which makes me think it's freshly malloc'd memory...
1089-
on the other hand, the address of the last line stays the
1090-
same as long as history isn't extended, so it appears to
1091-
be malloc'd but managed by the history package... */
1092-
free(state);
10931100
}
10941101
/* Copy the malloc'ed buffer into a PyMem_Malloc'ed one and
10951102
release the original. */

0 commit comments

Comments
 (0)