[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] unwind protect for bind -x commands
From: |
Grisha Levit |
Subject: |
[PATCH] unwind protect for bind -x commands |
Date: |
Tue, 27 Jun 2023 18:47:56 -0400 |
If SIGINT is received during the execution of a bind -x command, the
memory allocated for the saved parser state is leaked and the READLINE_*
variables remain in the environment
* pcomplete.c,bashline.c:
- uw_restore_parser_state,uw_rl_set_signals: move from pcomplete.c to
bashline.c
* bashline.h:
- extern declarations for uw_restore_parser_state, uw_rl_set_signals
* bashline.c:
- unbind_bindx_vars,uw_unbind_bindx_vars: new function to unbind shell
variables set by bind -x commands
- bash_execute_unix_command: use unbind_bindx_vars, add unwind-protects
for rl_set_signals, restore_parser_state, unbind_bindx_vars
The existing use of uw_restore_parser_state in gen_shell_function_matches
creates a 'restrict' copy of the pointer to the saved parser state.
I don't really understand why that is, so I didn't do that in
bash_execute_unix_command, but wanted to note here just in case.
---
bashline.c | 40 ++++++++++++++++++++++++++++++++++------
bashline.h | 3 +++
pcomplete.c | 12 ------------
3 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/bashline.c b/bashline.c
index 02f36e3a..70d6778f 100644
--- a/bashline.c
+++ b/bashline.c
@@ -4428,6 +4428,34 @@ readline_set_char_offset (int ind, int *varp)
}
}
+void
+uw_restore_parser_state (void *ps)
+{
+ restore_parser_state (ps);
+}
+
+void
+uw_rl_set_signals (void *ignore)
+{
+ rl_set_signals ();
+}
+
+static void
+unbind_bindx_vars (void)
+{
+ check_unbind_variable ("READLINE_LINE");
+ check_unbind_variable ("READLINE_POINT");
+ check_unbind_variable ("READLINE_MARK");
+ check_unbind_variable ("READLINE_ARGUMENT");
+ array_needs_making = 1;
+}
+
+static void
+uw_unbind_bindx_vars (void *ignore)
+{
+ unbind_bindx_vars ();
+}
+
int
bash_execute_unix_command (int count, int key)
{
@@ -4507,11 +4535,16 @@ bash_execute_unix_command (int count, int key)
}
array_needs_making = 1;
+ begin_unwind_frame ("bindx");
save_parser_state (&ps);
+ add_unwind_protect (uw_unbind_bindx_vars, NULL);
+ add_unwind_protect (uw_restore_parser_state, &ps);
+ add_unwind_protect (uw_rl_set_signals, NULL);
rl_clear_signals ();
r = parse_and_execute (savestring (cmd),
"bash_execute_unix_command", SEVAL_NOHIST);
rl_set_signals ();
restore_parser_state (&ps);
+ discard_unwind_frame ("bindx");
v = find_variable ("READLINE_LINE");
maybe_make_readline_line (v ? value_cell (v) : 0);
@@ -4524,12 +4557,7 @@ bash_execute_unix_command (int count, int key)
if (v && legal_number (value_cell (v), &mi))
readline_set_char_offset (mi, &rl_mark);
- check_unbind_variable ("READLINE_LINE");
- check_unbind_variable ("READLINE_POINT");
- check_unbind_variable ("READLINE_MARK");
- check_unbind_variable ("READLINE_ARGUMENT");
- array_needs_making = 1;
-
+ unbind_bindx_vars ();
/* and restore the readline buffer and display after command execution. */
/* If we clear the last line of the prompt above, redraw only that last
line. If the command returns 124, we redraw unconditionally as in
diff --git a/bashline.h b/bashline.h
index d9fb7379..2079799a 100644
--- a/bashline.h
+++ b/bashline.h
@@ -56,6 +56,9 @@ extern char **bash_default_completion (const char *,
int, int, int, int);
extern void set_directory_hook (void);
/* Used by programmable completion code. */
+extern void uw_rl_set_signals (void *);
+extern void uw_restore_parser_state (void *);
+
extern char *command_word_completion_function (const char *, int);
extern char *bash_groupname_completion_function (const char *, int);
extern char *bash_servicename_completion_function (const char *, int);
diff --git a/pcomplete.c b/pcomplete.c
index 410a7b7d..717a1479 100644
--- a/pcomplete.c
+++ b/pcomplete.c
@@ -1030,18 +1030,6 @@ build_arg_list (const char *cmd, const char
*cname, const char *text, WORD_LIST
return ret;
}
-static void
-uw_restore_parser_state (void *ps)
-{
- restore_parser_state (ps);
-}
-
-static void
-uw_rl_set_signals (void *ignore)
-{
- rl_set_signals ();
-}
-
/* Build a command string with
$0 == cs->funcname (function to execute for completion list)
$1 == command name (command being completed)
--
2.41.0
0001-unwind-protect-for-bind-x-commands.patch
Description: Binary data
- [PATCH] unwind protect for bind -x commands,
Grisha Levit <=