]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix for adding `;' to nofork command substitution; IBM z/OS changes; fix for files...
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Jun 2023 18:21:03 +0000 (14:21 -0400)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Jun 2023 18:21:03 +0000 (14:21 -0400)
16 files changed:
CWRU/CWRU.chlog
MANIFEST
aclocal.m4
builtins/enable.def
builtins/evalfile.c
configure
configure.ac
findcmd.c
parse.y
print_cmd.c
subst.c
tests/alias.right
tests/alias.tests
tests/heredoc.right
tests/heredoc.tests
tests/heredoc9.sub [new file with mode: 0644]

index 8f45099f64e09ab27f601c31c287be429df2d3d4..e3dc20d9c5e472b103bdf73e50a336b3904940bd 100644 (file)
@@ -6494,3 +6494,57 @@ builtins/enable.def
        - enable_builtin: don't try to load a builtin that's not found if
          the -n flag is supplied.
          From a report from Emanuele Torre <torreemanuele6@gmail.com>
+
+parse.y
+       - parse_comsub: use was_word code again to make sure we add a closing
+         `;' if the last token parsed before the closing ';' or '\n' was a
+         word, no matter what character ends it.
+         From a report by Grisha Levit <grishalevit@gmail.com>
+
+aclocal.m4,configure.ac,findcmd.c
+       - IBM z/OS changes from Igor Todorovski <itodorov@ca.ibm.com>
+
+                                   6/1
+                                   ---
+parse.y
+       - shell_getc: if the shell is not interactive and reading from a
+         buffered stream or stdin, and not expanding an alias, add a
+         backslash to a line ending with <backslash><EOF> like we do when
+         reading from a string. This prevents a backslash-newline from
+         being discarded when we are removing backslash-newlines from the
+         input, since we will add a newline to shell_input_line in this case.
+         From a report by Rob Landley <rob@landley.net>
+
+parse.y
+       - parse_compound_assignment: check and compensate for an alias being
+         popped out from underneath this function by read_token() (e.g.,
+         alias L='m=("x")'. Since we don't push a new input source, we should
+         never restore pushed_string_list from the saved parser state, but
+         we check and only do this if we were expanding an alias when this
+         function was called.
+         From a report by Wiley Young <wyeth2485@gmail.com>
+
+                                   6/2
+                                   ---
+print_cmd.c
+       - print_if_command: make sure to print any pending here-documents after
+         printing the test.
+         From https://bugzilla.redhat.com/show_bug.cgi?id=2211214
+
+builtins/enable.def
+       - if -n is supplied with -f, attempt to load the builtin but mark it
+         as disabled after loading.
+         Suggested by Robert Elz <kre@munnari.OZ.AU>
+
+builtins/evalfile.c
+       - _evalfile: increment retain_fifos, so we don't delete any FIFOs or
+         pipes we inherited before sourcing this file; restore original value
+         before we return.
+         From https://savannah.gnu.org/support/index.php?110883
+
+                                   6/3
+                                   ---
+subst.c
+       - expand_string_dollar_quote: if singlequote_translations is set, there
+         is a chance for a use-after-free of `t'.
+         From a report by Grisha Levit <grishalevit@gmail.com>
index dfbdc62358997fcd071b46951b501bb20256ff76..7d7d313db95b6ff4749ca6cf65f68622fadda50f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1197,6 +1197,7 @@ tests/heredoc5.sub        f
 tests/heredoc6.sub     f
 tests/heredoc7.sub     f
 tests/heredoc8.sub     f
+tests/heredoc9.sub     f
 tests/herestr.tests    f
 tests/herestr.right    f
 tests/herestr1.sub     f
index 2a86c70c6922068e8f083ff1c89c089bcd16f4fb..96d638373f82e92c6031d6d212a538a3f1ef1155 100644 (file)
@@ -1573,13 +1573,15 @@ AC_DEFUN(BASH_CHECK_DEV_FD,
 [AC_MSG_CHECKING(whether /dev/fd is available)
 AC_CACHE_VAL(bash_cv_dev_fd,
 [bash_cv_dev_fd=""
-if test -d /dev/fd  && (exec test -r /dev/fd/0 < /dev/null) ; then
+if test -d /dev/fd && (exec test -r /dev/fd/0 < /dev/null) ; then
 # check for systems like FreeBSD 5 that only provide /dev/fd/[012]
    if (exec test -r /dev/fd/3 3</dev/null) ; then
      bash_cv_dev_fd=standard
    else
      bash_cv_dev_fd=absent
    fi
+elif test "$host_os" = "openedition" && (exec test -r /dev/fd0 < /dev/null); then
+  bash_cv_dev_fd=nodir         # /dev/fdN via character device
 fi
 if test -z "$bash_cv_dev_fd" ; then 
   if test -d /proc/self/fd && (exec test -r /proc/self/fd/0 < /dev/null) ; then
@@ -1596,6 +1598,9 @@ if test $bash_cv_dev_fd = "standard"; then
 elif test $bash_cv_dev_fd = "whacky"; then
   AC_DEFINE(HAVE_DEV_FD)
   AC_DEFINE(DEV_FD_PREFIX, "/proc/self/fd/")
+elif test $bash_cv_dev_fd = "nodir"; then
+  AC_DEFINE(HAVE_DEV_FD)
+  AC_DEFINE(DEV_FD_PREFIX, "/dev/fd")
 fi
 ])
 
index cb7b5e4e88fd46082d9c2dffa7d5dde8c87065f4..aa143760fc5835e399189337bf275e19d688c6d8 100644 (file)
@@ -435,6 +435,8 @@ dyn_load_builtin (WORD_LIST *list, int flags, char *filename)
       b->flags &= ~STATIC_BUILTIN;
       if (flags & SPECIAL)
        b->flags |= SPECIAL_BUILTIN;
+      if (flags & DISABLED)
+       b->flags &= ~BUILTIN_ENABLED;
       b->handle = handle;
 
       if (old_builtin)
index 548c563f1aee1b22bbad01cff7783380cbc6fbf4..6a242bda42ace8d2fb1e679eabb3bfd6de13ef4f 100644 (file)
@@ -218,6 +218,7 @@ file_error_and_exit:
       if (flags & FEVAL_NONINT)
        unwind_protect_int (interactive);
       unwind_protect_int (sourcelevel);
+      unwind_protect_int (retain_fifos);
     }
   else
     {
@@ -232,6 +233,8 @@ file_error_and_exit:
   return_catch_flag++;
   sourcelevel++;
 
+  retain_fifos++;                      /* XXX */
+
 #if defined (ARRAY_VARS)
   array_push (bash_source_a, (char *)filename);
   t = itos (executing_line_number ());
@@ -304,6 +307,7 @@ file_error_and_exit:
 #endif
       return_catch_flag--;
       sourcelevel--;
+      retain_fifos--;
       COPY_PROCENV (old_return_catch, return_catch);
     }
 
index d05e8509b1e51c877154da18dc4c71c9e86def89..b6d9aad26587f7147cfe86608bca92c19bf8edba 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac for Bash 5.2, version 5.051.
+# From configure.ac for Bash 5.2, version 5.052.
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.71 for bash 5.2-maint.
 #
@@ -3281,7 +3281,6 @@ m68k-sysv)        opt_bash_malloc=no ;;   # fixes file descriptor leak in closedir
 *-beos*)       opt_bash_malloc=no ;;   # they say it's suitable
 # These need additional investigation
 sparc-linux*)  opt_bash_malloc=no ;;   # sparc running linux; requires ELF
-i370-*)                opt_bash_malloc=no ;;   # IBM z/OS machines
 *-aix*)                opt_bash_malloc=no ;;   # AIX machines
 *-cygwin*)     opt_bash_malloc=no ;;   # Cygnus's CYGWIN environment
 # These lack a working sbrk(2)
@@ -3299,6 +3298,8 @@ riscv*-freebsd*)  opt_bash_malloc=no ;;
 *-nsk*)                opt_bash_malloc=no ;;   # HP NonStop
 *-haiku*)      opt_bash_malloc=no ;;   # Haiku OS
 *-genode*)     opt_bash_malloc=no ;;   # Genode has no sbrk
+i370-openedition*)     opt_bash_malloc=no LOCAL_LIBS=-lzoslib LIBS_FOR_BUILD=-lzoslib ;;       # IBM z/OS machines
+i370-*)                opt_bash_malloc=no ;;   # generic (?) IBM 370 machines
 esac
 
 # memory scrambling on free()
@@ -21628,13 +21629,15 @@ then :
   printf %s "(cached) " >&6
 else $as_nop
   bash_cv_dev_fd=""
-if test -d /dev/fd  && (exec test -r /dev/fd/0 < /dev/null) ; then
+if test -d /dev/fd && (exec test -r /dev/fd/0 < /dev/null) ; then
 # check for systems like FreeBSD 5 that only provide /dev/fd/[012]
    if (exec test -r /dev/fd/3 3</dev/null) ; then
      bash_cv_dev_fd=standard
    else
      bash_cv_dev_fd=absent
    fi
+elif test "$host_os" = "openedition" && (exec test -r /dev/fd0 < /dev/null); then
+  bash_cv_dev_fd=nodir         # /dev/fdN via character device
 fi
 if test -z "$bash_cv_dev_fd" ; then
   if test -d /proc/self/fd && (exec test -r /proc/self/fd/0 < /dev/null) ; then
@@ -21658,6 +21661,11 @@ elif test $bash_cv_dev_fd = "whacky"; then
 
   printf "%s\n" "#define DEV_FD_PREFIX \"/proc/self/fd/\"" >>confdefs.h
 
+elif test $bash_cv_dev_fd = "nodir"; then
+  printf "%s\n" "#define HAVE_DEV_FD 1" >>confdefs.h
+
+  printf "%s\n" "#define DEV_FD_PREFIX \"/dev/fd\"" >>confdefs.h
+
 fi
 
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether /dev/stdin stdout stderr are available" >&5
index db1c32f33e0a36b569d69221728ac4436d14e995..43237394963667d2466584e3febfe6407f6e06eb 100644 (file)
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
 #   You should have received a copy of the GNU General Public License
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-AC_REVISION([for Bash 5.2, version 5.051])dnl
+AC_REVISION([for Bash 5.2, version 5.052])dnl
 
 define(bashvers, 5.2)
 define(relstatus, maint)
@@ -75,7 +75,6 @@ m68k-sysv)    opt_bash_malloc=no ;;   # fixes file descriptor leak in closedir
 *-beos*)       opt_bash_malloc=no ;;   # they say it's suitable
 # These need additional investigation
 sparc-linux*)  opt_bash_malloc=no ;;   # sparc running linux; requires ELF
-i370-*)                opt_bash_malloc=no ;;   # IBM z/OS machines
 *-aix*)                opt_bash_malloc=no ;;   # AIX machines
 *-cygwin*)     opt_bash_malloc=no ;;   # Cygnus's CYGWIN environment
 # These lack a working sbrk(2)
@@ -93,6 +92,8 @@ riscv*-freebsd*)      opt_bash_malloc=no ;;
 *-nsk*)                opt_bash_malloc=no ;;   # HP NonStop
 *-haiku*)      opt_bash_malloc=no ;;   # Haiku OS
 *-genode*)     opt_bash_malloc=no ;;   # Genode has no sbrk
+i370-openedition*)     opt_bash_malloc=no LOCAL_LIBS=-lzoslib LIBS_FOR_BUILD=-lzoslib ;;       # IBM z/OS machines
+i370-*)                opt_bash_malloc=no ;;   # generic (?) IBM 370 machines
 esac
 
 # memory scrambling on free()
index bbb8ae928dc9ad911ae3dcc0f626ca2d12429d61..73c07bd80390c48e018aeb34c14708cb6ffd7d2a 100644 (file)
--- a/findcmd.c
+++ b/findcmd.c
@@ -117,7 +117,19 @@ file_status (const char *name)
 
   /* Determine whether this file exists or not. */
   if (stat (name, &finfo) < 0)
+#if defined (__MVS__) && defined (S_ISEXTL)
+    {
+      /* Workaround for z/OS not supporting stat on external links */
+      int old_errno = errno;
+      if (!(errno == ENOENT && lstat(name, &finfo) == 0 && S_ISEXTL(finfo.st_mode,finfo.st_genvalue)))
+       {
+         errno = old_errno;      /* lstat may reset errno */
+         return (0);
+       }
+    }
+#else
     return (0);
+#endif
 
   /* If the file is a directory, then it is not "executable" in the
      sense of the shell. */
diff --git a/parse.y b/parse.y
index 9151de74a0728f3d870824ae02355d7ad5b3786e..c139a4d7b0dc939fc91468f14886f6fa074899ee 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2603,6 +2603,10 @@ shell_getc (int remove_quoted_newline)
             word expansion). */
          if (bash_input.type == st_string && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline)
            shell_input_line[shell_input_line_len] = '\\';
+         else if (bash_input.type == st_bstream && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline)
+           shell_input_line[shell_input_line_len] = '\\';
+         else if (interactive == 0 && bash_input.type == st_stream && expanding_alias() == 0 && last_was_backslash && c == EOF && remove_quoted_newline)
+           shell_input_line[shell_input_line_len] = '\\';
          else
            shell_input_line[shell_input_line_len] = '\n';
          shell_input_line[shell_input_line_len + 1] = '\0';
@@ -4384,7 +4388,6 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
 
   r = yyparse ();
 
-#if 0
   if (open == '{')
     {
       if (current_token == shell_eof_token &&
@@ -4392,7 +4395,6 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
            (token_before_that == WORD || token_before_that == ASSIGNMENT_WORD))
        was_word = 1;
     }
-#endif
 
   if (need_here_doc > 0)
     {
@@ -4486,7 +4488,9 @@ INTERNAL_DEBUG(("current_token (%d) != shell_eof_token (%c)", current_token, she
       ret = xmalloc (retlen + 4);
       ret[0] = (dolbrace_spec == '|') ? '|' : ' ';
       strcpy (ret + 1, tcmd);          /* ( */
-      if (lastc != '\n' && lastc != ';' && lastc != '&')
+      if (was_word)
+       ret[retlen++] = ';';
+      else if (lastc != '\n' && lastc != ';' && lastc != '&')
        ret[retlen++] = ';';
       ret[retlen++] = ' ';
     }
@@ -6853,9 +6857,10 @@ static char *
 parse_compound_assignment (size_t *retlenp)
 {
   WORD_LIST *wl, *rl;
-  int tok, orig_line_number, assignok;
+  int tok, orig_line_number, assignok, ea, restore_pushed_strings;
   sh_parser_state_t ps;
   char *ret;
+  STRING_SAVER *ss;
 
   orig_line_number = line_number;
   save_parser_state (&ps);
@@ -6878,6 +6883,12 @@ parse_compound_assignment (size_t *retlenp)
 
   esacs_needed_count = expecting_in_token = 0;
 
+  /* We're not pushing any new input here, we're reading from the current input
+     source. If that's an alias, we have to be prepared for the alias to get
+     popped out from underneath us. */
+  ss = (ea = expanding_alias ()) ? pushed_string_list : (STRING_SAVER *)NULL;
+  restore_pushed_strings = 0;
+    
   while ((tok = read_token (READ)) != ')')
     {
       if (tok == '\n')                 /* Allow newlines in compound assignments */
@@ -6901,7 +6912,16 @@ parse_compound_assignment (size_t *retlenp)
       wl = make_word_list (yylval.word, wl);
     }
 
+  /* Check whether or not an alias got popped out from underneath us and
+     fix up after restore_parser_state. */
+  if (ea && ss && ss != pushed_string_list)
+    {
+      restore_pushed_strings = 1;
+      ss = pushed_string_list;
+    }
   restore_parser_state (&ps);
+  if (restore_pushed_strings)
+    pushed_string_list = ss;
 
   if (wl == &parse_string_error)
     {
index f7fca28c72f4038c0e29dc7d9384dd207688f79e..298708378edd449c09f82f66482164f6e8093924 100644 (file)
@@ -770,7 +770,14 @@ print_until_or_while (WHILE_COM *while_command, char *which)
   make_command_string_internal (while_command->test);
   PRINT_DEFERRED_HEREDOCS ("");
   semicolon ();
-  cprintf (" do\n");   /* was newline ("do\n"); */
+  if (was_heredoc)
+    {
+      indent (indentation);
+      cprintf ("do\n");
+      was_heredoc = 0;
+    }
+  else
+    cprintf (" do\n"); /* was newline ("do\n"); */
   indentation += indentation_amount;
   make_command_string_internal (while_command->action);
   PRINT_DEFERRED_HEREDOCS ("");
@@ -785,8 +792,16 @@ print_if_command (IF_COM *if_command)
   cprintf ("if ");
   skip_this_indent++;
   make_command_string_internal (if_command->test);
+  PRINT_DEFERRED_HEREDOCS ("");
   semicolon ();
-  cprintf (" then\n");
+  if (was_heredoc)
+    {
+      indent (indentation_amount);
+      cprintf ("then\n");
+      was_heredoc = 0;
+    }
+  else
+    cprintf (" then\n");
   indentation += indentation_amount;
   make_command_string_internal (if_command->true_case);
   PRINT_DEFERRED_HEREDOCS ("");
diff --git a/subst.c b/subst.c
index 08d9285e84d505f57fcc3bf87e3a89228c415e72..b93374b8eaf8a54343a62c7af81d087f9f93f4c3 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4231,12 +4231,17 @@ expand_string_dollar_quote (const char *string, int flags)
                  continue;
                }
              trans = locale_expand (t, 0, news-sindex, 0, &translen);
-             free (t);
              if (singlequote_translations &&
                    ((news-sindex-1) != translen || STREQN (t, trans, translen) == 0))
-               t = sh_single_quote (trans);
+               {
+                 free (t);
+                 t = sh_single_quote (trans);
+               }
              else
-               t = sh_mkdoublequoted (trans, translen, 0);
+               {
+                 free (t);
+                 t = sh_mkdoublequoted (trans, translen, 0);
+               }
              sindex = news;
            }
 #endif /* TRANSLATABLE_STRINGS */
index 5dbc5d3211bfe1e2f322f4c9fc799cc269ebecfa..7b883c7d8256ebf85c6ecc12435609f307876e14 100644 (file)
@@ -3,6 +3,7 @@ alias: 0
 ./alias.tests: line 38: qfoo: command not found
 quux
 hi
+declare -a m=([0]="x")
 bar
 value
 bar
index fd390c20e77210d264814bff62bf09045606ffba..c3a66f10266984e8ba41e84d705658679c33d5f0 100644 (file)
@@ -54,9 +54,12 @@ unalias foo bar baz
 alias foo='a=() b=""
 for i in 1; do echo hi; done'
 foo
-
 unalias foo
 
+alias L='m=("x")'
+L
+declare -p m
+
 ${THIS_SH} ./alias1.sub
 ${THIS_SH} ./alias2.sub
 ${THIS_SH} ./alias3.sub
index cc193f66601913a941c0f9280ad9a2d3271dd0e6..b7042ff9949f0063a9139d91f02e3b8f34b4c02e 100644 (file)
@@ -127,7 +127,29 @@ foo bar
 ./heredoc7.sub: line 29: foobar: command not found
 ./heredoc7.sub: line 30: EOF: command not found
 grep: *.c: No such file or directory
+foo () 
+{ 
+    echo begin;
+    if cat <<HERE
+contents
+HERE
+    then
+        echo 1 2;
+        echo 3 4;
+    fi
+}
+foo () 
+{ 
+    echo begin;
+    while read var <<HERE
+contents
+HERE
+    do
+        echo 1 2;
+        echo 3 4;
+    done
+}
 comsub here-string
-./heredoc.tests: line 156: warning: here-document at line 154 delimited by end-of-file (wanted `EOF')
+./heredoc.tests: line 159: warning: here-document at line 157 delimited by end-of-file (wanted `EOF')
 hi
 there
index c5d0f7b4a87f1af22cba175ab856212de0e1d99b..d3da798ddc06d1adc2614c094bd45234bb57980a 100644 (file)
@@ -144,6 +144,9 @@ ${THIS_SH} ./heredoc6.sub
 ${THIS_SH} ./heredoc7.sub
 ${THIS_SH} ./heredoc8.sub
 
+# various tests for printing here-documents in function bodies
+${THIS_SH} ./heredoc9.sub
+
 echo $(
        cat <<< "comsub here-string"
 )
diff --git a/tests/heredoc9.sub b/tests/heredoc9.sub
new file mode 100644 (file)
index 0000000..a38dba3
--- /dev/null
@@ -0,0 +1,44 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# various issues with printing here-documents as part of function bodies
+
+foo()
+{
+echo begin
+if cat << HERE
+contents
+HERE
+then
+       echo 1 2
+       echo 3 4
+fi
+}
+
+declare -pf foo
+
+foo()
+{
+echo begin
+while read var << HERE
+contents
+HERE
+do
+       echo 1 2
+       echo 3 4
+done
+}
+
+declare -pf foo
+unset -f foo