bash: Import upstream patches
authorJeffery To <redacted>
Tue, 28 Apr 2020 06:35:49 +0000 (14:35 +0800)
committerJeffery To <redacted>
Tue, 28 Apr 2020 20:38:24 +0000 (04:38 +0800)
Source:
https://ftp.gnu.org/gnu/bash/bash-5.0-patches/
(bash50-003 to bash50-017)

Signed-off-by: Jeffery To <redacted>
16 files changed:
utils/bash/Makefile
utils/bash/patches/103-bash50-003.patch [new file with mode: 0644]
utils/bash/patches/104-bash50-004.patch [new file with mode: 0644]
utils/bash/patches/105-bash50-005.patch [new file with mode: 0644]
utils/bash/patches/106-bash50-006.patch [new file with mode: 0644]
utils/bash/patches/107-bash50-007.patch [new file with mode: 0644]
utils/bash/patches/108-bash50-008.patch [new file with mode: 0644]
utils/bash/patches/109-bash50-009.patch [new file with mode: 0644]
utils/bash/patches/110-bash50-010.patch [new file with mode: 0644]
utils/bash/patches/111-bash50-011.patch [new file with mode: 0644]
utils/bash/patches/112-bash50-012.patch [new file with mode: 0644]
utils/bash/patches/113-bash50-013.patch [new file with mode: 0644]
utils/bash/patches/114-bash50-014.patch [new file with mode: 0644]
utils/bash/patches/115-bash50-015.patch [new file with mode: 0644]
utils/bash/patches/116-bash50-016.patch [new file with mode: 0644]
utils/bash/patches/117-bash50-017.patch [new file with mode: 0644]

index ce3f03ddc732c89c2bdc1ebd71e020db4c22e30b..ad1eab364da80f09dd3c1aadc52e1e4717fbc7a1 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=bash
 PKG_VERSION:=5.0
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=@GNU/bash
diff --git a/utils/bash/patches/103-bash50-003.patch b/utils/bash/patches/103-bash50-003.patch
new file mode 100644 (file)
index 0000000..b2c7cf6
--- /dev/null
@@ -0,0 +1,239 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-003
+
+Bug-Reported-by:       Andrew Church <achurch+bash@achurch.org>
+Bug-Reference-ID:      <5c534aa2.04371@msgid.achurch.org>
+Bug-Reference-URL:     http://lists.gnu.org/archive/html/bug-bash/2019-01/msg00276.html
+
+Bug-Description:
+
+There are several incompatibilities in how bash-5.0 processes pathname
+expansion (globbing) of filename arguments that have backslashes in the
+directory portion.
+
+Patch (apply with `patch -p0'):
+
+*** a/lib/glob/glob_loop.c     2019-01-16 16:13:21.000000000 -0500
+--- b/lib/glob/glob_loop.c     2019-02-01 09:45:11.000000000 -0500
+***************
+*** 27,34 ****
+    register const GCHAR *p;
+    register GCHAR c;
+!   int bopen;
+  
+    p = pattern;
+!   bopen = 0;
+  
+    while ((c = *p++) != L('\0'))
+--- 27,34 ----
+    register const GCHAR *p;
+    register GCHAR c;
+!   int bopen, bsquote;
+  
+    p = pattern;
+!   bopen = bsquote = 0;
+  
+    while ((c = *p++) != L('\0'))
+***************
+*** 56,66 ****
+        case L('\\'):
+       /* Don't let the pattern end in a backslash (GMATCH returns no match
+!         if the pattern ends in a backslash anyway), but otherwise return 1,
+!         since the matching engine uses backslash as an escape character
+!         and it can be removed. */
+!      return (*p != L('\0'));
+        }
+  
+!   return 0;
+  }
+  
+--- 56,75 ----
+        case L('\\'):
+       /* Don't let the pattern end in a backslash (GMATCH returns no match
+!         if the pattern ends in a backslash anyway), but otherwise note that 
+!         we have seen this, since the matching engine uses backslash as an
+!         escape character and it can be removed. We return 2 later if we
+!         have seen only backslash-escaped characters, so interested callers
+!         know they can shortcut and just dequote the pathname. */
+!      if (*p != L('\0'))
+!        {
+!          p++;
+!          bsquote = 1;
+!          continue;
+!        }
+!      else    /* (*p == L('\0')) */
+!        return 0;
+        }
+  
+!   return bsquote ? 2 : 0;
+  }
+  
+*** a/lib/glob/glob.h  2013-10-28 14:46:12.000000000 -0400
+--- b/lib/glob/glob.h  2019-03-07 11:06:47.000000000 -0500
+***************
+*** 31,34 ****
+--- 31,35 ----
+  #define GX_ADDCURDIR 0x200   /* internal -- add passed directory name */
+  #define GX_GLOBSTAR  0x400   /* turn on special handling of ** */
++ #define GX_RECURSE   0x800   /* internal -- glob_filename called recursively */
+  
+  extern int glob_pattern_p __P((const char *));
+*** a/lib/glob/glob.c  2018-09-20 10:53:23.000000000 -0400
+--- b/lib/glob/glob.c  2019-03-07 14:23:43.000000000 -0500
+***************
+*** 1062,1066 ****
+    unsigned int directory_len;
+    int free_dirname;                  /* flag */
+!   int dflags;
+  
+    result = (char **) malloc (sizeof (char *));
+--- 1078,1082 ----
+    unsigned int directory_len;
+    int free_dirname;                  /* flag */
+!   int dflags, hasglob;
+  
+    result = (char **) malloc (sizeof (char *));
+***************
+*** 1111,1117 ****
+      }
+  
+    /* If directory_name contains globbing characters, then we
+!      have to expand the previous levels.  Just recurse. */
+!   if (directory_len > 0 && glob_pattern_p (directory_name))
+      {
+        char **directories, *d, *p;
+--- 1127,1136 ----
+      }
+  
++   hasglob = 0;
+    /* If directory_name contains globbing characters, then we
+!      have to expand the previous levels.  Just recurse.
+!      If glob_pattern_p returns != [0,1] we have a pattern that has backslash
+!      quotes but no unquoted glob pattern characters. We dequote it below. */
+!   if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1)
+      {
+        char **directories, *d, *p;
+***************
+*** 1176,1180 ****
+       d[directory_len - 1] = '\0';
+  
+!       directories = glob_filename (d, dflags);
+  
+        if (free_dirname)
+--- 1195,1199 ----
+       d[directory_len - 1] = '\0';
+  
+!       directories = glob_filename (d, dflags|GX_RECURSE);
+  
+        if (free_dirname)
+***************
+*** 1333,1336 ****
+--- 1352,1369 ----
+         return (NULL);
+       }
++       /* If we have a directory name with quoted characters, and we are
++       being called recursively to glob the directory portion of a pathname,
++       we need to dequote the directory name before returning it so the
++       caller can read the directory */
++       if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) != 0)
++      {
++        dequote_pathname (directory_name);
++        directory_len = strlen (directory_name);
++      }
++ 
++       /* We could check whether or not the dequoted directory_name is a
++       directory and return it here, returning the original directory_name
++       if not, but we don't do that yet. I'm not sure it matters. */
++ 
+        /* Handle GX_MARKDIRS here. */
+        result[0] = (char *) malloc (directory_len + 1);
+*** a/pathexp.c        2018-04-29 17:44:48.000000000 -0400
+--- b/pathexp.c        2019-01-31 20:19:41.000000000 -0500
+***************
+*** 66,74 ****
+    register int c;
+    char *send;
+!   int open;
+  
+    DECLARE_MBSTATE;
+  
+!   open = 0;
+    send = string + strlen (string);
+  
+--- 66,74 ----
+    register int c;
+    char *send;
+!   int open, bsquote;
+  
+    DECLARE_MBSTATE;
+  
+!   open = bsquote = 0;
+    send = string + strlen (string);
+  
+***************
+*** 101,105 ****
+          globbing. */
+       case '\\':
+!        return (*string != 0);
+                 
+       case CTLESC:
+--- 101,112 ----
+          globbing. */
+       case '\\':
+!        if (*string != '\0' && *string != '/')
+!          {
+!            bsquote = 1;
+!            string++;
+!            continue;
+!          }
+!        else if (*string == 0)
+!          return (0);
+                 
+       case CTLESC:
+***************
+*** 118,122 ****
+  #endif
+      }
+!   return (0);
+  }
+  
+--- 125,130 ----
+  #endif
+      }
+! 
+!   return (bsquote ? 2 : 0);
+  }
+  
+*** a/bashline.c       2019-01-16 16:13:21.000000000 -0500
+--- b/bashline.c       2019-02-22 09:29:08.000000000 -0500
+***************
+*** 3753,3757 ****
+  
+       case '\\':
+!        if (*string == 0)
+           return (0);           
+       }
+--- 3766,3770 ----
+  
+       case '\\':
+!        if (*string++ == 0)
+           return (0);           
+       }
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 2
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 3
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/104-bash50-004.patch b/utils/bash/patches/104-bash50-004.patch
new file mode 100644 (file)
index 0000000..fd4d0d7
--- /dev/null
@@ -0,0 +1,53 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-004
+
+Bug-Reported-by:       Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Bug-Reference-ID:      <87lg0g8aiw.fsf@fifthhorseman.net>
+Bug-Reference-URL:     http://lists.gnu.org/archive/html/bug-bash/2019-04/msg00076.html
+
+Bug-Description:
+
+In bash-5.0, the `wait' builtin without arguments waits for all children of the
+shell. This includes children it `inherited' at shell invocation time. This
+patch modifies the behavior to not wait for these inherited children, some
+of which might be long-lived.
+
+Patch (apply with `patch -p0'):
+
+*** a/jobs.c   2018-12-06 11:44:34.000000000 -0500
+--- b/jobs.c   2019-04-12 15:15:10.000000000 -0400
+***************
+*** 2489,2496 ****
+    wait_procsubs ();
+    reap_procsubs ();
+! #if 1
+    /* We don't want to wait indefinitely if we have stopped children. */
+-   /* XXX - should add a loop that goes through the list of process
+-      substitutions and waits for each proc in turn before this code. */
+    if (any_stopped == 0)
+      {
+--- 2490,2495 ----
+    wait_procsubs ();
+    reap_procsubs ();
+! #if 0
+    /* We don't want to wait indefinitely if we have stopped children. */
+    if (any_stopped == 0)
+      {
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 3
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 4
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/105-bash50-005.patch b/utils/bash/patches/105-bash50-005.patch
new file mode 100644 (file)
index 0000000..3bdce4c
--- /dev/null
@@ -0,0 +1,110 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-005
+
+Bug-Reported-by:       Brad Spencer <bspencer@blackberry.com>
+Bug-Reference-ID:      <1b993ff2-ce4f-662a-6be4-393457362e47@blackberry.com>
+Bug-Reference-URL:     http://lists.gnu.org/archive/html/bug-bash/2019-01/msg00250.html
+
+Bug-Description:
+
+In certain cases, bash optimizes out a fork() call too early and prevents
+traps from running.
+
+Patch (apply with `patch -p0'):
+
+*** a/command.h        2018-07-20 21:16:31.000000000 -0400
+--- b/command.h        2019-02-20 11:09:36.000000000 -0500
+***************
+*** 187,190 ****
+--- 188,192 ----
+  #define CMD_LASTPIPE     0x2000
+  #define CMD_STDPATH      0x4000      /* use standard path for command lookup */
++ #define CMD_TRY_OPTIMIZING  0x8000   /* try to optimize this simple command */
+  
+  /* What a command looks like. */
+*** a/builtins/evalstring.c    2018-12-26 11:19:21.000000000 -0500
+--- b/builtins/evalstring.c    2019-01-29 14:15:19.000000000 -0500
+***************
+*** 101,104 ****
+--- 101,113 ----
+  }
+  
++ int
++ can_optimize_connection (command)
++      COMMAND *command;
++ {
++   return (*bash_input.location.string == '\0' &&
++        (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
++        command->value.Connection->second->type == cm_simple);
++ }
++ 
+  void
+  optimize_fork (command)
+***************
+*** 106,110 ****
+  {
+    if (command->type == cm_connection &&
+!       (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR) &&
+        should_suppress_fork (command->value.Connection->second))
+      {
+--- 115,120 ----
+  {
+    if (command->type == cm_connection &&
+!       (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
+!       (command->value.Connection->second->flags & CMD_TRY_OPTIMIZING) &&
+        should_suppress_fork (command->value.Connection->second))
+      {
+***************
+*** 413,418 ****
+                 command->value.Simple->flags |= CMD_NO_FORK;
+               }
+!            else if (command->type == cm_connection)
+!              optimize_fork (command);
+  #endif /* ONESHOT */
+  
+--- 423,438 ----
+                 command->value.Simple->flags |= CMD_NO_FORK;
+               }
+! 
+!            /* Can't optimize forks out here execept for simple commands.
+!               This knows that the parser sets up commands as left-side heavy
+!               (&& and || are left-associative) and after the single parse,
+!               if we are at the end of the command string, the last in a
+!               series of connection commands is
+!               command->value.Connection->second. */
+!            else if (command->type == cm_connection && can_optimize_connection (command))
+!              {
+!                command->value.Connection->second->flags |= CMD_TRY_OPTIMIZING;
+!                command->value.Connection->second->value.Simple->flags |= CMD_TRY_OPTIMIZING;
+!              }
+  #endif /* ONESHOT */
+  
+*** a/execute_cmd.c    2018-12-05 09:05:14.000000000 -0500
+--- b/execute_cmd.c    2019-01-25 15:59:00.000000000 -0500
+***************
+*** 2768,2771 ****
+--- 2768,2773 ----
+          (exec_result != EXECUTION_SUCCESS)))
+       {
++        optimize_fork (command);
++ 
+         second = command->value.Connection->second;
+         if (ignore_return && second)
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 4
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 5
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/106-bash50-006.patch b/utils/bash/patches/106-bash50-006.patch
new file mode 100644 (file)
index 0000000..8812845
--- /dev/null
@@ -0,0 +1,47 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-006
+
+Bug-Reported-by:       Tomas Mozes <hydrapolic@gmail.com>
+Bug-Reference-ID:      <CAG6MAzQumLU2vhnmr1UrYAUQAFW5Yo8hfM_sEibX9RJQWJkRrA@mail.gmail.com>
+Bug-Reference-URL:     http://lists.gnu.org/archive/html/bug-bash/2019-03/msg00037.html
+
+Bug-Description:
+
+Bash-5.0 did not build successfully if SYSLOG_HISTORY was defined without
+also defining SYSLOG_SHOPT.
+
+Patch (apply with `patch -p0'):
+
+*** a/builtins/shopt.def       2018-10-05 14:49:02.000000000 -0400
+--- b/builtins/shopt.def       2019-01-23 09:55:22.000000000 -0500
+***************
+*** 123,127 ****
+  #endif
+  
+! #if defined (SYSLOG_HISTORY) && defined (SYSLOG_SHOPT)
+  extern int syslog_history;
+  #endif
+--- 123,127 ----
+  #endif
+  
+! #if defined (SYSLOG_HISTORY)
+  extern int syslog_history;
+  #endif
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 5
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 6
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/107-bash50-007.patch b/utils/bash/patches/107-bash50-007.patch
new file mode 100644 (file)
index 0000000..05b7141
--- /dev/null
@@ -0,0 +1,62 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-007
+
+Bug-Reported-by:       Grisha Levit <grishalevit@gmail.com>
+Bug-Reference-ID:      <CAMu=BroHapG1AS3xB5SQaCX2XKu=-E2Ob9uW6LNuHvd=YohrDw@mail.gmail.com>
+Bug-Reference-URL:     http://lists.gnu.org/archive/html/bug-bash/2019-02/msg00067.html
+
+Bug-Description:
+
+Running `exec' when job control was disabled, even temporarily, but after it
+had been initialized, could leave the terminal in the wrong process group for
+the executed process.
+
+Patch (apply with `patch -p0'):
+
+*** a/jobs.c   2018-12-06 11:44:34.000000000 -0500
+--- b/jobs.c   2019-04-12 15:15:10.000000000 -0400
+***************
+*** 4838,4850 ****
+  {
+    if (job_control)
+!     {
+!       terminate_stopped_jobs ();
+  
+!       if (original_pgrp >= 0)
+!      give_terminal_to (original_pgrp, 1);
+!     }
+  
+!   if (original_pgrp >= 0)
+!     setpgid (0, original_pgrp);
+  }
+  
+--- 4838,4848 ----
+  {
+    if (job_control)
+!     terminate_stopped_jobs ();
+  
+!   if (original_pgrp >= 0 && terminal_pgrp != original_pgrp)
+!     give_terminal_to (original_pgrp, 1);
+  
+!   if (original_pgrp >= 0 && setpgid (0, original_pgrp) == 0)
+!     shell_pgrp = original_pgrp;
+  }
+  
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 6
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 7
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/108-bash50-008.patch b/utils/bash/patches/108-bash50-008.patch
new file mode 100644 (file)
index 0000000..25d1e69
--- /dev/null
@@ -0,0 +1,68 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-008
+
+Bug-Reported-by:       Michael Albinus <michael.albinus@gmx.de>
+Bug-Reference-ID:      <87bm36k3kz.fsf@gmx.de>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2019-02/msg00111.html
+
+Bug-Description:
+
+When HISTSIZE is set to 0, history expansion can leave the history length
+set to an incorrect value, leading to subsequent attempts to access invalid
+memory.
+
+Patch (apply with `patch -p0'):
+
+*** a/bashhist.c       2018-07-05 22:41:14.000000000 -0400
+--- b/bashhist.c       2019-02-20 16:20:04.000000000 -0500
+***************
+*** 561,573 ****
+    if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
+      {
+        /* If we are expanding the second or later line of a multi-line
+        command, decrease history_length so references to history expansions
+        in these lines refer to the previous history entry and not the
+        current command. */
+        if (history_length > 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
+          history_length--;
+        expanded = history_expand (line, &history_value);
+        if (history_length >= 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
+!         history_length++;
+  
+        if (expanded)
+--- 561,576 ----
+    if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
+      {
++       int old_len;
++ 
+        /* If we are expanding the second or later line of a multi-line
+        command, decrease history_length so references to history expansions
+        in these lines refer to the previous history entry and not the
+        current command. */
++       old_len = history_length;
+        if (history_length > 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
+          history_length--;
+        expanded = history_expand (line, &history_value);
+        if (history_length >= 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1)
+!         history_length = old_len;
+  
+        if (expanded)
+
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 7
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 8
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/109-bash50-009.patch b/utils/bash/patches/109-bash50-009.patch
new file mode 100644 (file)
index 0000000..ac02be6
--- /dev/null
@@ -0,0 +1,42 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-009
+
+Bug-Reported-by:       chet.ramey@case.edu
+Bug-Reference-ID:
+Bug-Reference-URL:
+
+Bug-Description:
+
+The history file reading code doesn't close the file descriptor open to
+the history file when it encounters a zero-length file.
+
+Patch (apply with `patch -p0'):
+
+*** a/lib/readline/histfile.c  2018-06-11 09:14:52.000000000 -0400
+--- b/lib/readline/histfile.c  2019-05-16 15:55:57.000000000 -0400
+***************
+*** 306,309 ****
+--- 312,316 ----
+      {
+        free (input);
++       close (file);
+        return 0;      /* don't waste time if we don't have to */
+      }
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 8
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 9
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/110-bash50-010.patch b/utils/bash/patches/110-bash50-010.patch
new file mode 100644 (file)
index 0000000..1dfe39f
--- /dev/null
@@ -0,0 +1,172 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-010
+
+Bug-Reported-by:       Thorsten Glaser <tg@mirbsd.de>
+Bug-Reference-ID:      <156622962831.19438.16374961114836556294.reportbug@tglase.lan.tarent.de>
+Bug-Reference-URL:     https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=935115
+
+Bug-Description:
+
+Bash-5.0 changed the way assignment statements preceding special builtins
+and shell functions were handled in posix mode. They automatically created
+or modified global variables instead of modifying existing local variables
+as in bash-4.4.
+
+The bash-4.4 posix-mode semantics were buggy, and resulted in creating
+local variables where they were not intended and modifying global variables
+and local variables simultaneously.
+
+The bash-5.0 changes were intended to fix this issue, but did not preserve
+enough backwards compatibility. The posix standard also changed what it
+required in these cases, so bash-5.0 is not bound by the strict conformance
+requirements that existed in previous issues of the standard.
+
+This patch modifies the bash-5.0 posix mode behavior in an effort to restore
+some backwards compatibility and rationalize the behavior in the presence of
+local variables. It
+
+1. Changes the assignment semantics to be more similar to standalone assignment
+   statements: assignments preceding a function call or special builtin while
+   executing in a shell function will modify the value of a local variable
+   with the same name for the duration of the function's execution;
+
+2. Changes assignments preceding shell function calls or special builtins
+   from within a shell function to no longer create or modify global variables
+   in the presence of a local variable with the same name;
+
+3. Assignment statements preceding a shell function call or special builtin
+   at the global scope continue to modify the (global) calling environment,
+   but are unaffected by assignments preceding function calls or special
+   builtins within a function, as described in item 2. This is also similar
+   to the behavior of a standalone assignment statement.
+
+Patch (apply with `patch -p0'):
+
+*** a/variables.c      2018-12-18 11:07:21.000000000 -0500
+--- b/variables.c      2019-08-22 10:53:44.000000000 -0400
+***************
+*** 4461,4467 ****
+  
+  /* Take a variable from an assignment statement preceding a posix special
+!    builtin (including `return') and create a global variable from it. This
+!    is called from merge_temporary_env, which is only called when in posix
+!    mode. */
+  static void
+  push_posix_temp_var (data)
+--- 4461,4467 ----
+  
+  /* Take a variable from an assignment statement preceding a posix special
+!    builtin (including `return') and create a variable from it as if a
+!    standalone assignment statement had been performed. This is called from
+!    merge_temporary_env, which is only called when in posix mode. */
+  static void
+  push_posix_temp_var (data)
+***************
+*** 4473,4486 ****
+    var = (SHELL_VAR *)data;
+  
+!   binding_table = global_variables->table;
+!   if (binding_table == 0)
+!     binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
+! 
+!   v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
+  
+    /* global variables are no longer temporary and don't need propagating. */
+!   var->attributes &= ~(att_tempvar|att_propagate);
+    if (v)
+!     v->attributes |= var->attributes;
+  
+    if (find_special_var (var->name) >= 0)
+--- 4473,4497 ----
+    var = (SHELL_VAR *)data;
+  
+!   /* Just like do_assignment_internal(). This makes assignments preceding
+!      special builtins act like standalone assignment statements when in
+!      posix mode, satisfying the posix requirement that this affect the
+!      "current execution environment." */
+!   v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP);
+! 
+!   /* If this modifies an existing local variable, v->context will be non-zero.
+!      If it comes back with v->context == 0, we bound at the global context.
+!      Set binding_table appropriately. It doesn't matter whether it's correct
+!      if the variable is local, only that it's not global_variables->table */
+!   binding_table = v->context ? shell_variables->table : global_variables->table;
+  
+    /* global variables are no longer temporary and don't need propagating. */
+!   if (binding_table == global_variables->table)
+!     var->attributes &= ~(att_tempvar|att_propagate);
+! 
+    if (v)
+!     {
+!       v->attributes |= var->attributes;
+!       v->attributes &= ~att_tempvar; /* not a temp var now */
+!     }
+  
+    if (find_special_var (var->name) >= 0)
+***************
+*** 4576,4587 ****
+  {
+    int i;
+  
+    tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
+    tempvar_list[tvlist_ind = 0] = 0;
+!     
+!   hash_flush (temporary_env, pushf);
+!   hash_dispose (temporary_env);
+    temporary_env = (HASH_TABLE *)NULL;
+  
+    tempvar_list[tvlist_ind] = 0;
+  
+--- 4587,4601 ----
+  {
+    int i;
++   HASH_TABLE *disposer;
+  
+    tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
+    tempvar_list[tvlist_ind = 0] = 0;
+! 
+!   disposer = temporary_env;
+    temporary_env = (HASH_TABLE *)NULL;
+  
++   hash_flush (disposer, pushf);
++   hash_dispose (disposer);
++ 
+    tempvar_list[tvlist_ind] = 0;
+  
+*** a/tests/varenv.right       2018-12-17 15:39:48.000000000 -0500
+--- b/tests/varenv.right       2019-08-22 16:05:25.000000000 -0400
+***************
+*** 147,153 ****
+  outside: declare -- var="one"
+  inside: declare -x var="value"
+! outside: declare -x var="value"
+! inside: declare -- var="local"
+! outside: declare -x var="global"
+  foo=<unset> environment foo=
+  foo=foo environment foo=foo
+--- 147,153 ----
+  outside: declare -- var="one"
+  inside: declare -x var="value"
+! outside: declare -- var="outside"
+! inside: declare -x var="global"
+! outside: declare -- var="outside"
+  foo=<unset> environment foo=
+  foo=foo environment foo=foo
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 9
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 10
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/111-bash50-011.patch b/utils/bash/patches/111-bash50-011.patch
new file mode 100644 (file)
index 0000000..10611aa
--- /dev/null
@@ -0,0 +1,59 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-011
+
+Bug-Reported-by:       Matt Whitlock
+Bug-Reference-ID:      
+Bug-Reference-URL:     https://savannah.gnu.org/support/?109671
+
+Bug-Description:
+
+The conditional command did not perform appropriate quoted null character
+removal on its arguments, causing syntax errors and attempts to stat
+invalid pathnames.
+
+Patch (apply with `patch -p0'):
+
+*** a/subst.c  2018-12-22 17:43:37.000000000 -0500
+--- b/subst.c  2019-04-14 13:25:41.000000000 -0400
+***************
+*** 3626,3630 ****
+     SPECIAL is 2, this is an rhs argument for the =~ operator, and should
+     be quoted appropriately for regcomp/regexec.  The caller is responsible
+!    for removing the backslashes if the unquoted word is needed later. */   
+  char *
+  cond_expand_word (w, special)
+--- 3642,3648 ----
+     SPECIAL is 2, this is an rhs argument for the =~ operator, and should
+     be quoted appropriately for regcomp/regexec.  The caller is responsible
+!    for removing the backslashes if the unquoted word is needed later. In
+!    any case, since we don't perform word splitting, we need to do quoted
+!    null character removal. */
+  char *
+  cond_expand_word (w, special)
+***************
+*** 3647,3650 ****
+--- 3665,3670 ----
+        if (special == 0)                      /* LHS */
+       {
++        if (l->word)
++          word_list_remove_quoted_nulls (l);
+         dequote_list (l);
+         r = string_list (l);
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 10
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 11
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/112-bash50-012.patch b/utils/bash/patches/112-bash50-012.patch
new file mode 100644 (file)
index 0000000..7812879
--- /dev/null
@@ -0,0 +1,64 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-012
+
+Bug-Reported-by:       lessbug@qq.com
+Bug-Reference-ID:      <tencent_6AA531D9A5CC4121D86BD5CDA2E0DA98C605@qq.com>
+Bug-Reference-URL:
+
+Bug-Description:
+
+When using previous-history to go back beyond the beginning of the history list,
+it's possible to move to an incorrect partial line.
+
+Patch (apply with `patch -p0'):
+
+*** a/lib/readline/misc.c      2017-07-07 17:30:12.000000000 -0400
+--- b/lib/readline/misc.c      2019-05-16 11:43:46.000000000 -0400
+***************
+*** 577,580 ****
+--- 590,594 ----
+  {
+    HIST_ENTRY *old_temp, *temp;
++   int had_saved_line;
+  
+    if (count < 0)
+***************
+*** 589,592 ****
+--- 603,607 ----
+  
+    /* If we don't have a line saved, then save this one. */
++   had_saved_line = _rl_saved_line_for_history != 0;
+    rl_maybe_save_line ();
+  
+***************
+*** 612,616 ****
+    if (temp == 0)
+      {
+!       rl_maybe_unsave_line ();
+        rl_ding ();
+      }
+--- 627,632 ----
+    if (temp == 0)
+      {
+!       if (had_saved_line == 0)
+!         _rl_free_saved_history_line ();
+        rl_ding ();
+      }
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 11
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 12
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/113-bash50-013.patch b/utils/bash/patches/113-bash50-013.patch
new file mode 100644 (file)
index 0000000..b933e22
--- /dev/null
@@ -0,0 +1,73 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-013
+
+Bug-Reported-by:       HIROSE Masaaki <hirose31@gmail.com>
+Bug-Reference-ID:      <CAGSOfA-RqiTe=+GsXsDKyZrrMWH4bDbXgMVVegMa6OjqC5xbnQ@mail.gmail.com>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2019-05/msg00038.html
+
+Bug-Description:
+
+Reading history entries with timestamps can result in history entries joined
+by linefeeds.
+
+Patch (apply with `patch -p0'):
+
+*** a/lib/readline/histfile.c  2018-06-11 09:14:52.000000000 -0400
+--- b/lib/readline/histfile.c  2019-05-16 15:55:57.000000000 -0400
+***************
+*** 370,376 ****
+  
+    has_timestamps = HIST_TIMESTAMP_START (buffer);
+!   history_multiline_entries += has_timestamps && history_write_timestamps;  
+  
+    /* Skip lines until we are at FROM. */
+    for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
+      if (*line_end == '\n')
+--- 370,378 ----
+  
+    has_timestamps = HIST_TIMESTAMP_START (buffer);
+!   history_multiline_entries += has_timestamps && history_write_timestamps;
+  
+    /* Skip lines until we are at FROM. */
++   if (has_timestamps)
++     last_ts = buffer;
+    for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
+      if (*line_end == '\n')
+***************
+*** 381,385 ****
+--- 383,398 ----
+       if (HIST_TIMESTAMP_START(p) == 0)
+         current_line++;
++      else
++        last_ts = p;
+       line_start = p;
++      /* If we are at the last line (current_line == from) but we have
++         timestamps (has_timestamps), then line_start points to the
++         text of the last command, and we need to skip to its end. */
++      if (current_line >= from && has_timestamps)
++        {
++          for (line_end = p; line_end < bufend && *line_end != '\n'; line_end++)
++            ;
++          line_start = (*line_end == '\n') ? line_end + 1 : line_end;
++        }
+        }
+  
+
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 12
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 13
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/114-bash50-014.patch b/utils/bash/patches/114-bash50-014.patch
new file mode 100644 (file)
index 0000000..05f9d31
--- /dev/null
@@ -0,0 +1,52 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-014
+
+Bug-Reported-by:       Johannes Hielscher <jhielscher@posteo.de>
+Bug-Reference-ID:      <20190208205048.77c25a83@hordevm>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2019-02/msg00032.html
+
+Bug-Description:
+
+If the current line is empty, using the emacs C-xC-e binding to enter the
+editor will edit the previous command instead of the current (empty) one.
+
+Patch (apply with `patch -p0'):
+
+*** a/bashline.c       2019-01-16 16:13:21.000000000 -0500
+--- b/bashline.c       2019-02-11 11:18:57.000000000 -0500
+***************
+*** 962,970 ****
+        finished with the command, so we should not ignore the last command */
+        using_history ();
+!       if (rl_line_buffer[0])
+!      {
+!        current_command_line_count++; /* for rl_newline above */
+!        bash_add_history (rl_line_buffer);
+!      }
+        current_command_line_count = 0;        /* for dummy history entry */
+        bash_add_history ("");
+--- 965,970 ----
+        finished with the command, so we should not ignore the last command */
+        using_history ();
+!       current_command_line_count++;  /* for rl_newline above */
+!       bash_add_history (rl_line_buffer);
+        current_command_line_count = 0;        /* for dummy history entry */
+        bash_add_history ("");
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 13
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 14
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/115-bash50-015.patch b/utils/bash/patches/115-bash50-015.patch
new file mode 100644 (file)
index 0000000..c4cbefe
--- /dev/null
@@ -0,0 +1,78 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-015
+
+Bug-Reported-by:       Yu Kou <ckyoog@gmail.com>
+Bug-Reference-ID:      <CAAqoF9Ko3nAShJXGzucafs-ByUagzZ4nbQonwEkwC7s9UqfWKw@mail.gmail.com>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2019-05/msg00032.html
+
+Bug-Description:
+
+If alias expansion is enabled when processing the command argument to the
+`-c' option, an alias is defined in that command, and the command ends with
+the invocation of that alias, the shell's command parser can prematurely
+terminate before the entire command is executed.
+
+Patch (apply with `patch -p0'):
+
+*** a/builtins/evalstring.c    2019-01-29 14:15:19.000000000 -0500
+--- b/builtins/evalstring.c    2019-05-15 14:19:36.000000000 -0400
+***************
+*** 92,95 ****
+--- 92,96 ----
+         running_trap == 0 &&
+         *bash_input.location.string == '\0' &&
++        parser_expanding_alias () == 0 &&
+         command->type == cm_simple &&
+         signal_is_trapped (EXIT_TRAP) == 0 &&
+***************
+*** 106,109 ****
+--- 107,111 ----
+  {
+    return (*bash_input.location.string == '\0' &&
++        parser_expanding_alias () == 0 &&
+         (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') &&
+         command->value.Connection->second->type == cm_simple);
+***************
+*** 291,295 ****
+    with_input_from_string (string, from_file);
+    clear_shell_input_line ();
+!   while (*(bash_input.location.string))
+      {
+        command = (COMMAND *)NULL;
+--- 293,297 ----
+    with_input_from_string (string, from_file);
+    clear_shell_input_line ();
+!   while (*(bash_input.location.string) || parser_expanding_alias ())
+      {
+        command = (COMMAND *)NULL;
+***************
+*** 546,550 ****
+  
+    with_input_from_string (string, from_file);
+!   while (*(bash_input.location.string))
+      {
+        command = (COMMAND *)NULL;
+--- 548,552 ----
+  
+    with_input_from_string (string, from_file);
+!   while (*(bash_input.location.string))              /* XXX - parser_expanding_alias () ? */
+      {
+        command = (COMMAND *)NULL;
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 14
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 15
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/116-bash50-016.patch b/utils/bash/patches/116-bash50-016.patch
new file mode 100644 (file)
index 0000000..46aad0e
--- /dev/null
@@ -0,0 +1,58 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-016
+
+Bug-Reported-by:       sunnycemetery@gmail.com
+Bug-Reference-ID:      <20190316041534.GB22884@midnight>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2019-03/msg00070.html
+
+Bug-Description:
+
+Bash waits too long to reap /dev/fd process substitutions used as redirections
+with loops and group commands, which can lead to file descriptor exhaustion.
+
+Patch (apply with `patch -p0'):
+
+*** a/execute_cmd.c    2019-04-19 15:46:36.000000000 -0400
+--- b/execute_cmd.c    2019-07-01 16:45:49.000000000 -0400
+***************
+*** 1104,1107 ****
+--- 1085,1104 ----
+        discard_unwind_frame ("internal_fifos");
+      }
++ # if defined (HAVE_DEV_FD)
++   /* Reap process substitutions at the end of loops */
++   switch (command->type)
++     {
++     case cm_while:
++     case cm_until:
++     case cm_for:
++     case cm_group:
++ #    if defined (ARITH_FOR_COMMAND)
++     case cm_arith_for:
++ #    endif
++       reap_procsubs ();
++     default:
++       break;
++     }
++ #  endif /* HAVE_DEV_FD */
+  #endif
+  
+
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 15
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
diff --git a/utils/bash/patches/117-bash50-017.patch b/utils/bash/patches/117-bash50-017.patch
new file mode 100644 (file)
index 0000000..5facd4d
--- /dev/null
@@ -0,0 +1,289 @@
+                            BASH PATCH REPORT
+                            =================
+
+Bash-Release:  5.0
+Patch-ID:      bash50-017
+
+Bug-Reported-by:       Valentin Lab <valentin.lab@kalysto.org>
+Bug-Reference-ID:      <ab981b9c-60a5-46d0-b7e6-a6d88b80df50@kalysto.org>
+Bug-Reference-URL:     https://lists.gnu.org/archive/html/bug-bash/2020-03/msg00062.html
+
+Bug-Description:
+
+There were cases where patch 16 reaped process substitution file descriptors
+(or FIFOs) and processes to early. This is a better fix for the problem that
+bash50-016 attempted to solve.
+
+Patch (apply with `patch -p0'):
+
+*** a/subst.c  2019-08-29 11:16:49.000000000 -0400
+--- b/subst.c  2020-04-02 16:24:19.000000000 -0400
+***************
+*** 5337,5341 ****
+  }
+  
+! char *
+  copy_fifo_list (sizep)
+       int *sizep;
+--- 5337,5341 ----
+  }
+  
+! void *
+  copy_fifo_list (sizep)
+       int *sizep;
+***************
+*** 5343,5347 ****
+    if (sizep)
+      *sizep = 0;
+!   return (char *)NULL;
+  }
+  
+--- 5343,5347 ----
+    if (sizep)
+      *sizep = 0;
+!   return (void *)NULL;
+  }
+  
+***************
+*** 5409,5414 ****
+       if (fifo_list[i].file)
+         {
+!          fifo_list[j].file = fifo_list[i].file;
+!          fifo_list[j].proc = fifo_list[i].proc;
+           j++;
+         }
+--- 5409,5419 ----
+       if (fifo_list[i].file)
+         {
+!          if (i != j)
+!            {
+!              fifo_list[j].file = fifo_list[i].file;
+!              fifo_list[j].proc = fifo_list[i].proc;
+!              fifo_list[i].file = (char *)NULL;
+!              fifo_list[i].proc = 0;
+!            }
+           j++;
+         }
+***************
+*** 5426,5433 ****
+  void
+  close_new_fifos (list, lsize)
+!      char *list;
+       int lsize;
+  {
+    int i;
+  
+    if (list == 0)
+--- 5431,5439 ----
+  void
+  close_new_fifos (list, lsize)
+!      void *list;
+       int lsize;
+  {
+    int i;
++   char *plist;
+  
+    if (list == 0)
+***************
+*** 5437,5442 ****
+      }
+  
+!   for (i = 0; i < lsize; i++)
+!     if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
+        unlink_fifo (i);
+  
+--- 5443,5448 ----
+      }
+  
+!   for (plist = (char *)list, i = 0; i < lsize; i++)
+!     if (plist[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
+        unlink_fifo (i);
+  
+***************
+*** 5560,5568 ****
+  }
+  
+! char *
+  copy_fifo_list (sizep)
+       int *sizep;
+  {
+!   char *ret;
+  
+    if (nfds == 0 || totfds == 0)
+--- 5566,5574 ----
+  }
+  
+! void *
+  copy_fifo_list (sizep)
+       int *sizep;
+  {
+!   void *ret;
+  
+    if (nfds == 0 || totfds == 0)
+***************
+*** 5570,5579 ****
+        if (sizep)
+       *sizep = 0;
+!       return (char *)NULL;
+      }
+  
+    if (sizep)
+      *sizep = totfds;
+!   ret = (char *)xmalloc (totfds * sizeof (pid_t));
+    return (memcpy (ret, dev_fd_list, totfds * sizeof (pid_t)));
+  }
+--- 5576,5585 ----
+        if (sizep)
+       *sizep = 0;
+!       return (void *)NULL;
+      }
+  
+    if (sizep)
+      *sizep = totfds;
+!   ret = xmalloc (totfds * sizeof (pid_t));
+    return (memcpy (ret, dev_fd_list, totfds * sizeof (pid_t)));
+  }
+***************
+*** 5648,5655 ****
+  void
+  close_new_fifos (list, lsize)
+!      char *list;
+       int lsize;
+  {
+    int i;
+  
+    if (list == 0)
+--- 5654,5662 ----
+  void
+  close_new_fifos (list, lsize)
+!      void *list;
+       int lsize;
+  {
+    int i;
++   pid_t *plist;
+  
+    if (list == 0)
+***************
+*** 5659,5664 ****
+      }
+  
+!   for (i = 0; i < lsize; i++)
+!     if (list[i] == 0 && i < totfds && dev_fd_list[i])
+        unlink_fifo (i);
+  
+--- 5666,5671 ----
+      }
+  
+!   for (plist = (pid_t *)list, i = 0; i < lsize; i++)
+!     if (plist[i] == 0 && i < totfds && dev_fd_list[i])
+        unlink_fifo (i);
+  
+*** a/subst.h  2018-10-21 18:46:09.000000000 -0400
+--- b/subst.h  2020-04-02 16:29:28.000000000 -0400
+***************
+*** 274,280 ****
+  extern void unlink_fifo __P((int));
+  
+! extern char *copy_fifo_list __P((int *));
+! extern void unlink_new_fifos __P((char *, int));
+! extern void close_new_fifos __P((char *, int));
+  
+  extern void clear_fifo_list __P((void));
+--- 274,279 ----
+  extern void unlink_fifo __P((int));
+  
+! extern void *copy_fifo_list __P((int *));
+! extern void close_new_fifos __P((void *, int));
+  
+  extern void clear_fifo_list __P((void));
+*** a/execute_cmd.c    2020-02-06 20:16:48.000000000 -0500
+--- b/execute_cmd.c    2020-04-02 17:00:10.000000000 -0400
+***************
+*** 565,569 ****
+  #if defined (PROCESS_SUBSTITUTION)
+    volatile int ofifo, nfifo, osize, saved_fifo;
+!   volatile char *ofifo_list;
+  #endif
+  
+--- 565,569 ----
+  #if defined (PROCESS_SUBSTITUTION)
+    volatile int ofifo, nfifo, osize, saved_fifo;
+!   volatile void *ofifo_list;
+  #endif
+  
+***************
+*** 751,760 ****
+  #  endif
+  
+!   if (variable_context != 0) /* XXX - also if sourcelevel != 0? */
+      {
+        ofifo = num_fifos ();
+        ofifo_list = copy_fifo_list ((int *)&osize);
+        begin_unwind_frame ("internal_fifos");
+!       add_unwind_protect (xfree, ofifo_list);
+        saved_fifo = 1;
+      }
+--- 751,762 ----
+  #  endif
+  
+!   /* XXX - also if sourcelevel != 0? */
+!   if (variable_context != 0)
+      {
+        ofifo = num_fifos ();
+        ofifo_list = copy_fifo_list ((int *)&osize);
+        begin_unwind_frame ("internal_fifos");
+!       if (ofifo_list)
+!      add_unwind_protect (xfree, ofifo_list);
+        saved_fifo = 1;
+      }
+***************
+*** 1100,1123 ****
+        nfifo = num_fifos ();
+        if (nfifo > ofifo)
+!      close_new_fifos ((char *)ofifo_list, osize);
+        free ((void *)ofifo_list);
+        discard_unwind_frame ("internal_fifos");
+      }
+- # if defined (HAVE_DEV_FD)
+-   /* Reap process substitutions at the end of loops */
+-   switch (command->type)
+-     {
+-     case cm_while:
+-     case cm_until:
+-     case cm_for:
+-     case cm_group:
+- #    if defined (ARITH_FOR_COMMAND)
+-     case cm_arith_for:
+- #    endif
+-       reap_procsubs ();
+-     default:
+-       break;
+-     }
+- #  endif /* HAVE_DEV_FD */
+  #endif
+  
+--- 1102,1109 ----
+        nfifo = num_fifos ();
+        if (nfifo > ofifo)
+!      close_new_fifos ((void *)ofifo_list, osize);
+        free ((void *)ofifo_list);
+        discard_unwind_frame ("internal_fifos");
+      }
+  #endif
+  
+
+*** a/patchlevel.h     2016-06-22 14:51:03.000000000 -0400
+--- b/patchlevel.h     2016-10-01 11:01:28.000000000 -0400
+***************
+*** 26,30 ****
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 16
+  
+  #endif /* _PATCHLEVEL_H_ */
+--- 26,30 ----
+     looks for to find the patch level (for the sccs version string). */
+  
+! #define PATCHLEVEL 17
+  
+  #endif /* _PATCHLEVEL_H_ */
git clone https://git.99rst.org/PROJECT