Issue #8065: Fix another memory leak in readline module, from failure to free

the result of a call to history_get_history_state.
This commit is contained in:
Mark Dickinson 2010-08-03 16:49:49 +00:00
parent 29b238e0dc
commit 6b54e1f782
2 changed files with 29 additions and 19 deletions

View File

@ -21,6 +21,9 @@ Core and Builtins
Extensions
----------
- Issue #8065: Fix memory leak in readline module (from failure to
free the result of history_get_history_state()).
- Issue #9450: Fix memory leak in readline.replace_history_item and
readline.remove_history_item for readline version >= 5.0.

View File

@ -534,6 +534,25 @@ PyDoc_STRVAR(doc_get_completer,
\n\
Returns current completer function.");
/* Private function to get current length of history. XXX It may be
* possible to replace this with a direct use of history_length instead,
* but it's not clear whether BSD's libedit keeps history_length up to date.
* See issue #8065.*/
static int
_py_get_history_length(void)
{
HISTORY_STATE *hist_st = history_get_history_state();
int length = hist_st->length;
/* the history docs don't say so, but the address of hist_st changes each
time history_get_history_state is called which makes me think it's
freshly malloc'd memory... on the other hand, the address of the last
line stays the same as long as history isn't extended, so it appears to
be malloc'd but managed by the history package... */
free(hist_st);
return length;
}
/* Exported function to get any element of history */
static PyObject *
@ -552,9 +571,7 @@ get_history_item(PyObject *self, PyObject *args)
* code doesn't have to worry about the
* difference.
*/
HISTORY_STATE *hist_st;
hist_st = history_get_history_state();
int length = _py_get_history_length();
idx --;
/*
@ -562,7 +579,7 @@ get_history_item(PyObject *self, PyObject *args)
* the index is out of range, therefore
* test for that and fail gracefully.
*/
if (idx < 0 || idx >= hist_st->length) {
if (idx < 0 || idx >= length) {
Py_RETURN_NONE;
}
}
@ -584,10 +601,7 @@ return the current contents of history item at index.");
static PyObject *
get_current_history_length(PyObject *self, PyObject *noarg)
{
HISTORY_STATE *hist_st;
hist_st = history_get_history_state();
return PyLong_FromLong(hist_st ? (long) hist_st->length : (long) 0);
return PyLong_FromLong((long)_py_get_history_length());
}
PyDoc_STRVAR(doc_get_current_history_length,
@ -1067,29 +1081,22 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
n = strlen(p);
if (n > 0) {
char *line;
HISTORY_STATE *state = history_get_history_state();
if (state->length > 0)
int length = _py_get_history_length();
if (length > 0)
#ifdef __APPLE__
if (using_libedit_emulation) {
/*
* Libedit's emulation uses 0-based indexes,
* the real readline uses 1-based indexes.
*/
line = history_get(state->length - 1)->line;
line = history_get(length - 1)->line;
} else
#endif /* __APPLE__ */
line = history_get(state->length)->line;
line = history_get(length)->line;
else
line = "";
if (strcmp(p, line))
add_history(p);
/* the history docs don't say so, but the address of state
changes each time history_get_history_state is called
which makes me think it's freshly malloc'd memory...
on the other hand, the address of the last line stays the
same as long as history isn't extended, so it appears to
be malloc'd but managed by the history package... */
free(state);
}
/* Copy the malloc'ed buffer into a PyMem_Malloc'ed one and
release the original. */