readline fix for rl_undo_list pointer aliasing; arith command sets word_top

This commit is contained in:
Chet Ramey
2023-03-06 10:50:45 -05:00
parent 0bd0fb5966
commit 277c21d2b2
14 changed files with 414 additions and 32 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
/* histlib.h -- internal definitions for the history library. */
/* Copyright (C) 1989-2009,2021-2022 Free Software Foundation, Inc.
/* Copyright (C) 1989-2009,2021-2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -91,6 +91,7 @@ extern int _hs_history_search (const char *, int, int);
/* history.c */
extern void _hs_replace_history_data (int, histdata_t *, histdata_t *);
extern int _hs_search_history_data (histdata_t *);
extern int _hs_at_end_of_history (void);
/* histfile.c */
+23 -3
View File
@@ -1,6 +1,6 @@
/* history.c -- standalone history library */
/* Copyright (C) 1989-2021 Free Software Foundation, Inc.
/* Copyright (C) 1989-2023 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -458,7 +458,7 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
}
last = -1;
for (i = 0; i < history_length; i++)
for (i = history_length - 1; i >= 0; i--)
{
entry = the_history[i];
if (entry == 0)
@@ -475,7 +475,27 @@ _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
entry = the_history[last];
entry->data = new; /* XXX - we don't check entry->old */
}
}
}
int
_hs_search_history_data (histdata_t *needle)
{
register int i;
HIST_ENTRY *entry;
if (history_length == 0 || the_history == 0)
return -1;
for (i = history_length - 1; i >= 0; i--)
{
entry = the_history[i];
if (entry == 0)
continue;
if (entry->data == needle)
return i;
}
return -1;
}
/* Remove history element WHICH from the history. The removed
element is returned to you so you can free the line, data,
+13 -8
View File
@@ -340,6 +340,9 @@ rl_maybe_replace_line (void)
xfree (temp->line);
FREE (temp->timestamp);
xfree (temp);
/* XXX - what about _rl_saved_line_for_history? if the saved undo list
is rl_undo_list, and we just put that into a history entry, should
we set the saved undo list to NULL? */
}
return 0;
}
@@ -385,14 +388,16 @@ _rl_free_saved_history_line (void)
{
if (_rl_saved_line_for_history)
{
if (rl_undo_list && rl_undo_list == (UNDO_LIST *)_rl_saved_line_for_history->data)
rl_undo_list = 0;
/* Have to free this separately because _rl_free_history entry can't:
it doesn't know whether or not this has application data. Only the
callers that know this is _rl_saved_line_for_history can know that
it's an undo list. */
if (_rl_saved_line_for_history->data)
_rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
UNDO_LIST *sentinel;
sentinel = (UNDO_LIST *)_rl_saved_line_for_history->data;
/* We should only free `data' if it's not the current rl_undo_list and
it's not the `data' member in a history entry somewhere. We have to
free it separately because only the callers know it's an undo list. */
if (sentinel && sentinel != rl_undo_list && _hs_search_history_data ((histdata_t *)sentinel) < 0)
_rl_free_undo_list (sentinel);
_rl_free_history_entry (_rl_saved_line_for_history);
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
}
+3 -1
View File
@@ -88,8 +88,10 @@ make_history_line_current (HIST_ENTRY *entry)
xlist = _rl_saved_line_for_history ? (UNDO_LIST *)_rl_saved_line_for_history->data : 0;
/* At this point, rl_undo_list points to a private search string list. */
if (rl_undo_list && rl_undo_list != (UNDO_LIST *)entry->data && rl_undo_list != xlist)
if (rl_undo_list && rl_undo_list != (UNDO_LIST *)entry->data && rl_undo_list != xlist &&
_hs_search_history_data ((histdata_t *)rl_undo_list) < 0)
rl_free_undo_list ();
rl_undo_list = 0; /* XXX */
/* Now we create a new undo list with a single insert for this text.
WE DON'T CHANGE THE ORIGINAL HISTORY ENTRY UNDO LIST */