[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] completion display interrupt leak handling
From: |
Grisha Levit |
Subject: |
[PATCH] completion display interrupt leak handling |
Date: |
Sat, 17 Jun 2023 04:28:41 -0400 |
When readline's display of completion matches is interrupted, the match
list is only freed for the '?' completion type but not for '!' and '@'
types. I couldn't find a specific reason for that to be the case so
hope this patch is an OK fix.
Also add freeing saved_line_buffer from rl_complete_internal to the
signal handler and freeing of matches in one spot where menu completion
doesn't do it.
* lib/readline/complete.c
- complete_sigcleanarg_t: new struct to hold _rl_complete_sigcleanup
argument
- _rl_complete_sigcleanup: use new struct instead of *matches pointer,
now also handles freeing saved_line
- rl_complete_internal: set up _rl_sigcleanup whenever display_matches
is called so we no longer leak matches and saved_line_buffer when
getting a SIGINT
- rl_menu_complete: free contents of matches instead of just pointer
when completion-query-items exceeded
---
lib/readline/complete.c | 61 ++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/lib/readline/complete.c b/lib/readline/complete.c
index bf7cc856..f8f08aa6 100644
--- a/lib/readline/complete.c
+++ b/lib/readline/complete.c
@@ -494,12 +494,19 @@ _rl_reset_completion_state (void)
rl_completion_quote_character = 0;
}
+typedef struct {
+ char **matches;
+ char *saved_line;
+} complete_sigcleanarg_t;
+
static void
_rl_complete_sigcleanup (int sig, void *ptr)
{
+ complete_sigcleanarg_t *arg = ptr;
if (sig == SIGINT) /* XXX - for now */
{
- _rl_free_match_list ((char **)ptr);
+ _rl_free_match_list (arg->matches);
+ FREE (arg->saved_line);
_rl_complete_display_matches_interrupt = 1;
}
}
@@ -2008,7 +2015,8 @@ rl_complete_internal (int what_to_do)
int start, end, delimiter, found_quote, i, nontrivial_lcd;
char *text, *saved_line_buffer;
char quote_char;
- int tlen, mlen, saved_last_completion_failed;
+ int tlen, mlen, saved_last_completion_failed, do_display;
+ complete_sigcleanarg_t cleanarg;
RL_SETSTATE(RL_STATE_COMPLETING);
@@ -2088,6 +2096,8 @@ rl_complete_internal (int what_to_do)
if (matches && matches[0] && *matches[0])
last_completion_failed = 0;
+ do_display = 0;
+
switch (what_to_do)
{
case TAB:
@@ -2121,13 +2131,13 @@ rl_complete_internal (int what_to_do)
{
if (what_to_do == '!')
{
- display_matches (matches);
+ do_display = 1;
break;
}
else if (what_to_do == '@')
{
if (nontrivial_lcd == 0)
- display_matches (matches);
+ do_display = 1;
break;
}
else if (rl_editing_mode != vi_mode)
@@ -2151,23 +2161,7 @@ rl_complete_internal (int what_to_do)
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
break;
}
-
- if (rl_completion_display_matches_hook == 0)
- {
- _rl_sigcleanup = _rl_complete_sigcleanup;
- _rl_sigcleanarg = matches;
- _rl_complete_display_matches_interrupt = 0;
- }
- display_matches (matches);
- if (_rl_complete_display_matches_interrupt)
- {
- matches = 0; /* already freed by rl_complete_sigcleanup */
- _rl_complete_display_matches_interrupt = 0;
- if (rl_signal_event_hook)
- (*rl_signal_event_hook) (); /* XXX */
- }
- _rl_sigcleanup = 0;
- _rl_sigcleanarg = 0;
+ do_display = 1;
break;
default:
@@ -2180,6 +2174,29 @@ rl_complete_internal (int what_to_do)
return 1;
}
+ if (do_display)
+ {
+ if (rl_completion_display_matches_hook == 0)
+ {
+ _rl_sigcleanup = _rl_complete_sigcleanup;
+ cleanarg.matches = matches;
+ cleanarg.saved_line = saved_line_buffer;
+ _rl_sigcleanarg = &cleanarg;
+ _rl_complete_display_matches_interrupt = 0;
+ }
+ display_matches (matches);
+ if (_rl_complete_display_matches_interrupt)
+ {
+ matches = 0; /* already freed by rl_complete_sigcleanup */
+ saved_line_buffer = 0;
+ _rl_complete_display_matches_interrupt = 0;
+ if (rl_signal_event_hook)
+ (*rl_signal_event_hook) (); /* XXX */
+ }
+ _rl_sigcleanup = 0;
+ _rl_sigcleanarg = 0;
+ }
+
_rl_free_match_list (matches);
/* Check to see if the line has changed through all of this
manipulation. */
@@ -2864,7 +2881,7 @@ rl_menu_complete (int count, int ignore)
if (rl_completion_query_items > 0 && match_list_size >=
rl_completion_query_items)
{
rl_ding ();
- FREE (matches);
+ _rl_free_match_list (matches);
matches = (char **)0;
full_completion = 1;
return (0);
0001-improve-completion-interrupt-handling.patch
Description: Text Data
- [PATCH] completion display interrupt leak handling,
Grisha Levit <=