components/bash/patches/bash43-033.patch
changeset 5518 c47fe0edc204
equal deleted inserted replaced
5517:7758049098f4 5518:c47fe0edc204
       
     1 			     BASH PATCH REPORT
       
     2 			     =================
       
     3 
       
     4 Bash-Release:	4.3
       
     5 Patch-ID:	bash43-033
       
     6 
       
     7 Bug-Reported-by:	[email protected], Jan Rome <[email protected]>
       
     8 Bug-Reference-ID:	<[email protected]>,
       
     9 			<[email protected]>
       
    10 Bug-Reference-URL:	http://lists.gnu.org/archive/html/bug-bash/2014-09/msg00029.html
       
    11 			http://lists.gnu.org/archive/html/bug-bash/2014-09/msg00030.html
       
    12 
       
    13 Bug-Description:
       
    14 
       
    15 Bash does not clean up the terminal state in all cases where bash or
       
    16 readline  modifies it and bash is subsequently terminated by a fatal signal.
       
    17 This happens when the `read' builtin modifies the terminal settings, both
       
    18 when readline is active and when it is not.  It occurs most often when a script
       
    19 installs a trap that exits on a signal without re-sending the signal to itself.
       
    20 
       
    21 Patch (apply with `patch -p0'):
       
    22 
       
    23 *** ../bash-4.3-patched/shell.c	2014-01-14 08:04:32.000000000 -0500
       
    24 --- shell.c	2014-12-22 10:27:50.000000000 -0500
       
    25 ***************
       
    26 *** 74,77 ****
       
    27 --- 74,78 ----
       
    28   
       
    29   #if defined (READLINE)
       
    30 + #  include <readline/readline.h>
       
    31   #  include "bashline.h"
       
    32   #endif
       
    33 ***************
       
    34 *** 910,913 ****
       
    35 --- 912,923 ----
       
    36     fflush (stderr);
       
    37   
       
    38 +   /* Clean up the terminal if we are in a state where it's been modified. */
       
    39 + #if defined (READLINE)
       
    40 +   if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function)
       
    41 +     (*rl_deprep_term_function) ();
       
    42 + #endif
       
    43 +   if (read_tty_modified ())
       
    44 +     read_tty_cleanup ();
       
    45 + 
       
    46     /* Do trap[0] if defined.  Allow it to override the exit status
       
    47        passed to us. */
       
    48 *** ../bash-4.3-patched/builtins/read.def	2014-10-01 12:57:38.000000000 -0400
       
    49 --- builtins/read.def	2014-12-22 10:48:54.000000000 -0500
       
    50 ***************
       
    51 *** 141,148 ****
       
    52   int sigalrm_seen;
       
    53   
       
    54 ! static int reading;
       
    55   static SigHandler *old_alrm;
       
    56   static unsigned char delim;
       
    57   
       
    58   /* In all cases, SIGALRM just sets a flag that we check periodically.  This
       
    59      avoids problems with the semi-tricky stuff we do with the xfree of
       
    60 --- 141,150 ----
       
    61   int sigalrm_seen;
       
    62   
       
    63 ! static int reading, tty_modified;
       
    64   static SigHandler *old_alrm;
       
    65   static unsigned char delim;
       
    66   
       
    67 + static struct ttsave termsave;
       
    68 + 
       
    69   /* In all cases, SIGALRM just sets a flag that we check periodically.  This
       
    70      avoids problems with the semi-tricky stuff we do with the xfree of
       
    71 ***************
       
    72 *** 189,193 ****
       
    73     SHELL_VAR *var;
       
    74     TTYSTRUCT ttattrs, ttset;
       
    75 -   struct ttsave termsave;
       
    76   #if defined (ARRAY_VARS)
       
    77     WORD_LIST *alist;
       
    78 --- 191,194 ----
       
    79 ***************
       
    80 *** 222,226 ****
       
    81     USE_VAR(lastsig);
       
    82   
       
    83 !   sigalrm_seen = reading = 0;
       
    84   
       
    85     i = 0;		/* Index into the string that we are reading. */
       
    86 --- 223,227 ----
       
    87     USE_VAR(lastsig);
       
    88   
       
    89 !   sigalrm_seen = reading = tty_modified = 0;
       
    90   
       
    91     i = 0;		/* Index into the string that we are reading. */
       
    92 ***************
       
    93 *** 439,442 ****
       
    94 --- 440,445 ----
       
    95   	  goto assign_vars;
       
    96   	}
       
    97 +       if (interactive_shell == 0)
       
    98 + 	initialize_terminating_signals ();
       
    99         old_alrm = set_signal_handler (SIGALRM, sigalrm);
       
   100         add_unwind_protect (reset_alarm, (char *)NULL);
       
   101 ***************
       
   102 *** 483,487 ****
       
   103 --- 486,493 ----
       
   104   	  if (i < 0)
       
   105   	    sh_ttyerror (1);
       
   106 + 	  tty_modified = 1;
       
   107   	  add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
       
   108 + 	  if (interactive_shell == 0)
       
   109 + 	    initialize_terminating_signals ();
       
   110   	}
       
   111       }
       
   112 ***************
       
   113 *** 498,502 ****
       
   114 --- 504,511 ----
       
   115   	sh_ttyerror (1);
       
   116   
       
   117 +       tty_modified = 1;
       
   118         add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
       
   119 +       if (interactive_shell == 0)
       
   120 + 	initialize_terminating_signals ();
       
   121       }
       
   122   
       
   123 ***************
       
   124 *** 589,592 ****
       
   125 --- 598,603 ----
       
   126   	  else
       
   127   	    lastsig = 0;
       
   128 + 	  if (terminating_signal && tty_modified)
       
   129 + 	    ttyrestore (&termsave);	/* fix terminal before exiting */
       
   130   	  CHECK_TERMSIG;
       
   131   	  eof = 1;
       
   132 ***************
       
   133 *** 979,982 ****
       
   134 --- 990,1007 ----
       
   135   {
       
   136     ttsetattr (ttp->fd, ttp->attrs);
       
   137 +   tty_modified = 0;
       
   138 + }
       
   139 + 
       
   140 + void
       
   141 + read_tty_cleanup ()
       
   142 + {
       
   143 +   if (tty_modified)
       
   144 +     ttyrestore (&termsave);
       
   145 + }
       
   146 + 
       
   147 + int
       
   148 + read_tty_modified ()
       
   149 + {
       
   150 +   return (tty_modified);
       
   151   }
       
   152   
       
   153 *** ../bash-4.3-patched/builtins/common.h	2014-10-01 12:57:47.000000000 -0400
       
   154 --- builtins/common.h	2014-12-22 10:10:14.000000000 -0500
       
   155 ***************
       
   156 *** 123,126 ****
       
   157 --- 141,148 ----
       
   158   extern void getopts_reset __P((int));
       
   159   
       
   160 + /* Functions from read.def */
       
   161 + extern void read_tty_cleanup __P((void));
       
   162 + extern int read_tty_modified __P((void));
       
   163 + 
       
   164   /* Functions from set.def */
       
   165   extern int minus_o_option_value __P((char *));
       
   166 *** ../bash-4.3-patched/bashline.c	2014-05-14 09:22:39.000000000 -0400
       
   167 --- bashline.c	2014-09-08 11:28:56.000000000 -0400
       
   168 ***************
       
   169 *** 203,206 ****
       
   170 --- 203,207 ----
       
   171   extern int array_needs_making;
       
   172   extern int posixly_correct, no_symbolic_links;
       
   173 + extern int sigalrm_seen;
       
   174   extern char *current_prompt_string, *ps1_prompt;
       
   175   extern STRING_INT_ALIST word_token_alist[];
       
   176 ***************
       
   177 *** 4209,4214 ****
       
   178     /* If we're going to longjmp to top_level, make sure we clean up readline.
       
   179        check_signals will call QUIT, which will eventually longjmp to top_level,
       
   180 !      calling run_interrupt_trap along the way. */
       
   181 !   if (interrupt_state)
       
   182       rl_cleanup_after_signal ();
       
   183     bashline_reset_event_hook ();
       
   184 --- 4262,4268 ----
       
   185     /* If we're going to longjmp to top_level, make sure we clean up readline.
       
   186        check_signals will call QUIT, which will eventually longjmp to top_level,
       
   187 !      calling run_interrupt_trap along the way.  The check for sigalrm_seen is
       
   188 !      to clean up the read builtin's state. */
       
   189 !   if (terminating_signal || interrupt_state || sigalrm_seen)
       
   190       rl_cleanup_after_signal ();
       
   191     bashline_reset_event_hook ();
       
   192 *** ../bash-4.3-patched/sig.c	2014-01-10 15:06:06.000000000 -0500
       
   193 --- sig.c	2014-09-08 11:26:33.000000000 -0400
       
   194 ***************
       
   195 *** 533,538 ****
       
   196     /* Set the event hook so readline will call it after the signal handlers
       
   197        finish executing, so if this interrupted character input we can get
       
   198 !      quick response. */
       
   199 !   if (interactive_shell && interactive && no_line_editing == 0)
       
   200       bashline_set_event_hook ();
       
   201   #endif
       
   202 --- 533,540 ----
       
   203     /* Set the event hook so readline will call it after the signal handlers
       
   204        finish executing, so if this interrupted character input we can get
       
   205 !      quick response.  If readline is active or has modified the terminal we
       
   206 !      need to set this no matter what the signal is, though the check for
       
   207 !      RL_STATE_TERMPREPPED is possibly redundant. */
       
   208 !   if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
       
   209       bashline_set_event_hook ();
       
   210   #endif
       
   211 *** ../bash-4.3/patchlevel.h	2012-12-29 10:47:57.000000000 -0500
       
   212 --- patchlevel.h	2014-03-20 20:01:28.000000000 -0400
       
   213 ***************
       
   214 *** 26,30 ****
       
   215      looks for to find the patch level (for the sccs version string). */
       
   216   
       
   217 ! #define PATCHLEVEL 32
       
   218   
       
   219   #endif /* _PATCHLEVEL_H_ */
       
   220 --- 26,30 ----
       
   221      looks for to find the patch level (for the sccs version string). */
       
   222   
       
   223 ! #define PATCHLEVEL 33
       
   224   
       
   225   #endif /* _PATCHLEVEL_H_ */