bug-bash
[Top][All Lists]
Advanced

[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

Attachment: 0001-unwind-protect-for-bind-x-commands.patch
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]