On 7/5/25 2:57 PM, Carl Johnson wrote:

Bash Version: 5.3
Patch Level: 0
Release Status: release

Description:
When alias definition contains the 'unalias' builtin with the alias's
name as its argument with a newline anywhere after the builtin
invocation, running the alias when PROMPT_COMMAND is not empty causes
a segmentation fault.

Repeat-By:
Start an bash shell, run the following code:
```bash
PROMPT_COMMAND=:
alias a=$'unalias a\n'
a
```
The result is a segmentation fault.

Thanks for the report. In the general case, evaluating the value of a shell
variable as a command should save and restore the parser state. In this
edge case, though, it's not necessary because PROMPT_COMMAND is only
evaluated before parsing a command. The attached patch should fix it.

Chet


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    c...@case.edu    http://tiswww.cwru.edu/~chet/
*** ../bash-5.3/parse.y Thu Jun 12 12:36:06 2025
--- parse.y     Sun Jul  6 16:46:00 2025
***************
*** 3009,3023 ****
  
  void
! execute_variable_command (const char *command, const char *vname)
  {
    char *last_lastarg;
    sh_parser_state_t ps;
  
!   save_parser_state (&ps);
    last_lastarg = save_lastarg ();
  
    parse_and_execute (savestring (command), vname, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY);
  
!   restore_parser_state (&ps);
    bind_lastarg (last_lastarg);
    FREE (last_lastarg);
--- 3009,3025 ----
  
  void
! execute_variable_command (const char *command, const char *vname, int flags)
  {
    char *last_lastarg;
    sh_parser_state_t ps;
  
!   if (flags)
!     save_parser_state (&ps);
    last_lastarg = save_lastarg ();
  
    parse_and_execute (savestring (command), vname, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY);
  
!   if (flags)
!     restore_parser_state (&ps);
    bind_lastarg (last_lastarg);
    FREE (last_lastarg);
*** ../bash-5.3/eval.c  Fri Mar  7 18:50:03 2025
--- eval.c      Sun Jul  6 16:49:18 2025
***************
*** 284,288 ****
  /* Caller ensures that A has a non-zero number of elements */
  int
! execute_array_command (ARRAY *a, void *v)
  {
    char *tag;
--- 284,288 ----
  /* Caller ensures that A has a non-zero number of elements */
  int
! execute_array_command (ARRAY *a, void *v, int flags)
  {
    char *tag;
***************
*** 296,300 ****
      {
        if (argv[i] && argv[i][0])
!       execute_variable_command (argv[i], tag);
      }
    strvec_dispose (argv);
--- 296,300 ----
      {
        if (argv[i] && argv[i][0])
!       execute_variable_command (argv[i], tag, flags);
      }
    strvec_dispose (argv);
***************
*** 319,323 ****
      {
        if ((pcmds = array_cell (pcv)) && array_num_elements (pcmds) > 0)
!       execute_array_command (pcmds, "PROMPT_COMMAND");
        return;
      }
--- 319,323 ----
      {
        if ((pcmds = array_cell (pcv)) && array_num_elements (pcmds) > 0)
!       execute_array_command (pcmds, "PROMPT_COMMAND", 0);
        return;
      }
***************
*** 328,332 ****
    command_to_execute = value_cell (pcv);
    if (command_to_execute && *command_to_execute)
!     execute_variable_command (command_to_execute, "PROMPT_COMMAND");
  }
  
--- 328,332 ----
    command_to_execute = value_cell (pcv);
    if (command_to_execute && *command_to_execute)
!     execute_variable_command (command_to_execute, "PROMPT_COMMAND", 0);
  }
  
*** ../bash-5.3/input.h Fri Mar 10 16:22:48 2023
--- input.h     Sun Jul  6 16:45:42 2025
***************
*** 100,104 ****
  extern int find_reserved_word (const char *);
  extern void gather_here_documents (void);
! extern void execute_variable_command (const char *, const char *);
  
  extern int *save_token_state (void);
--- 100,104 ----
  extern int find_reserved_word (const char *);
  extern void gather_here_documents (void);
! extern void execute_variable_command (const char *, const char *, int);
  
  extern int *save_token_state (void);
*** ../bash-5.3/array.h Wed Dec 28 14:00:47 2022
--- array.h     Sun Jul  6 16:47:27 2025
***************
*** 178,182 ****
  
  /* In eval.c, but uses ARRAY * */
! extern int execute_array_command (ARRAY *, void *);
  
  #endif /* _ARRAY_H_ */
--- 178,182 ----
  
  /* In eval.c, but uses ARRAY * */
! extern int execute_array_command (ARRAY *, void *, int);
  
  #endif /* _ARRAY_H_ */
*** ../bash-5.3/y.tab.c Mon Jun 30 09:56:25 2025
--- y.tab.c     Sun Jul  6 17:38:06 2025
***************
*** 5368,5382 ****
  
  void
! execute_variable_command (const char *command, const char *vname)
  {
    char *last_lastarg;
    sh_parser_state_t ps;
  
!   save_parser_state (&ps);
    last_lastarg = save_lastarg ();
  
    parse_and_execute (savestring (command), vname, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY);
  
!   restore_parser_state (&ps);
    bind_lastarg (last_lastarg);
    FREE (last_lastarg);
--- 5368,5384 ----
  
  void
! execute_variable_command (const char *command, const char *vname, int flags)
  {
    char *last_lastarg;
    sh_parser_state_t ps;
  
!   if (flags)
!     save_parser_state (&ps);
    last_lastarg = save_lastarg ();
  
    parse_and_execute (savestring (command), vname, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY);
  
!   if (flags)
!     restore_parser_state (&ps);
    bind_lastarg (last_lastarg);
    FREE (last_lastarg);

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to