]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix for parameter expansions that contain valid and invalid expansions; avoid stale...
authorChet Ramey <chet.ramey@case.edu>
Mon, 4 Aug 2025 14:18:32 +0000 (10:18 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 4 Aug 2025 14:18:32 +0000 (10:18 -0400)
CWRU/CWRU.chlog
aclocal.m4
builtins/cd.def
configure
doc/bash.1
doc/bashref.texi
doc/version.texi
execute_cmd.c
lib/sh/getcwd.c
po/stamp-po [new file with mode: 0644]
subst.c

index bf82f2a3cdfbbb777e276dcc997e79c90e52b717..44336651c998fcc43fc39ce37bcf5b2c54427a7c 100644 (file)
@@ -11476,8 +11476,42 @@ command.h
        - revert changes to COMMAND and SIMPLE_COM from 7/16
          From a report by Jessica Clarke <jrtc27@jrtc27.com>
 
+parse.y
+       - pipeline: in BAR_AND form of the pipeline production, use a
+         REDIRECT ** to manipulate the redirection list instead of trying
+         to cast a COMAND * to a SIMPLE_COM *
+         From a report by Jessica Clarke <jrtc27@jrtc27.com>
+
 expr.c
        - expassign,expshift: avoid C23 undefined behavior when performing
          left and right arithmetic shifts
          From https://savannah.gnu.org/patch/?10532
          bkallus <benjamin.p.kallus.gr@dartmouth.edu>
+
+                                  7/28
+                                  ----
+subst.c
+       - expand_word_internal: if we see a `$' and call param_expand, pass a
+         local copy of expanded_something and OR it into expanded_something,
+         so this function can set it to 0 if we get a trailing $ or a $!
+         when there are no background pids.
+         From ahmedwaldsaaid@gmail.com via https://savannah.gnu.org/bugs/index.php?67358
+         Fix suggested by Oğuz <oguzismailuysal@gmail.com>
+
+                                   8/1
+                                   ---
+lib/sh/getcwd.c
+       - getcwd: set errno to 0 before calling readdir to avoid a stale
+         value if readdir() returns NULL and distinguish errors from the
+         end of the directory. If readdir() returns NULL without changing
+         errno, set it to ENOENT.
+         From a report by Richard Weinberger <richard@sigma-star.at>
+
+aclocal.m4
+       - BASH_CHECK_LIB_TERMCAP: add libtinfow to the library list to search
+         From a report by Дилян Палаузов <dilyan.palauzov@aegee.org>
+
+execute_cmd.c
+       - execute_subshell_builtin_or_function: fix to propagate exit statuses
+         of builtins run in subshells back to the calling shell
+         From https://savannah.gnu.org/support/?109840
index ae2d8aec96dc31e42fdfc650069e12fda3dd946b..8d72b67ea5e219e49109bd99a2c143895076b7e1 100644 (file)
@@ -934,10 +934,11 @@ AC_CACHE_VAL(bash_cv_termcap_lib,
 [AC_CHECK_FUNC(tgetent, bash_cv_termcap_lib=libc,
   [AC_CHECK_LIB(termcap, tgetent, bash_cv_termcap_lib=libtermcap,
     [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+      [AC_CHECK_LIB(tinfow, tgetent, bash_cv_termcap_lib=libtinfow,
         [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
-           [AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
-                [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
-                   bash_cv_termcap_lib=gnutermcap)])])])])])])
+         [AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
+            [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+             bash_cv_termcap_lib=gnutermcap)])])])])])])])
 if test "X$_bash_needmsg" = "Xyes"; then
 AC_MSG_CHECKING(which library has the termcap functions)
 fi
@@ -952,6 +953,9 @@ TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libtinfo; then
 TERMCAP_LIB=-ltinfo
 TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libncursesw; then
 TERMCAP_LIB=-lncursesw
 TERMCAP_DEP=
index 5b39cb52b907eb76ff9ceec592633c3f8ef7d34b..108862b8747f65fffa4ce89c13eea3b556d766c7 100644 (file)
@@ -79,12 +79,13 @@ $SHORT_DOC cd [-L|[-P [-e]]] [-@] [dir]
 Change the shell working directory.
 
 Change the current directory to DIR.  The default DIR is the value of the
-HOME shell variable. If DIR is "-", it is converted to $OLDPWD.
+HOME shell variable. If DIR is "-", it is converted to $OLDPWD. If DIR is
+the empty string, cd returns an error.
 
 The variable CDPATH defines the search path for the directory containing
 DIR.  Alternative directory names in CDPATH are separated by a colon (:).
-A null directory name is the same as the current directory.  If DIR begins
-with a slash (/), then CDPATH is not used.
+A null directory name in CDPATH is the same as the current directory.
+If DIR begins with a slash (/), then CDPATH is not used.
 
 If the directory is not found, and the shell option `cdable_vars' is set,
 the word is assumed to be  a variable name.  If that variable has a value,
index ccc7ea18d1cb0f1afd34af9ce62a2a265d5ff8ed..6288f0cb2f2f788ad4c96906ac61230e6a394587 100755 (executable)
--- a/configure
+++ b/configure
@@ -5570,6 +5570,53 @@ printf "%s\n" "$ac_cv_lib_tinfo_tgetent" >&6; }
 if test "x$ac_cv_lib_tinfo_tgetent" = xyes
 then :
   bash_cv_termcap_lib=libtinfo
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfow" >&5
+printf %s "checking for tgetent in -ltinfow... " >&6; }
+if test ${ac_cv_lib_tinfow_tgetent+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltinfow  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent (void);
+int
+main (void)
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_tinfow_tgetent=yes
+else case e in #(
+  e) ac_cv_lib_tinfow_tgetent=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfow_tgetent" >&5
+printf "%s\n" "$ac_cv_lib_tinfow_tgetent" >&6; }
+if test "x$ac_cv_lib_tinfow_tgetent" = xyes
+then :
+  bash_cv_termcap_lib=libtinfow
 else case e in #(
   e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
 printf %s "checking for tgetent in -lcurses... " >&6; }
@@ -5732,6 +5779,9 @@ esac
 fi
  ;;
 esac
+fi
+ ;;
+esac
 fi
 
 if test "X$_bash_needmsg" = "Xyes"; then
@@ -5750,6 +5800,9 @@ TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libtinfo; then
 TERMCAP_LIB=-ltinfo
 TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libncursesw; then
 TERMCAP_LIB=-lncursesw
 TERMCAP_DEP=
@@ -9357,8 +9410,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
         LIBS=$save_LIBS
         test $gl_pthread_api = yes && break
       done
-      echo "$as_me:9360: gl_pthread_api=$gl_pthread_api" >&5
-      echo "$as_me:9361: LIBPTHREAD=$LIBPTHREAD" >&5
+      echo "$as_me:9413: gl_pthread_api=$gl_pthread_api" >&5
+      echo "$as_me:9414: LIBPTHREAD=$LIBPTHREAD" >&5
 
       gl_pthread_in_glibc=no
       # On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9384,7 +9437,7 @@ rm -rf conftest*
 
           ;;
       esac
-      echo "$as_me:9387: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+      echo "$as_me:9440: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
 
       # Test for libpthread by looking for pthread_kill. (Not pthread_self,
       # since it is defined as a macro on OSF/1.)
@@ -9562,7 +9615,7 @@ fi
 
         fi
       fi
-      echo "$as_me:9565: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+      echo "$as_me:9618: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
     fi
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
 printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -9809,8 +9862,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
         LIBS=$save_LIBS
         test $gl_pthread_api = yes && break
       done
-      echo "$as_me:9812: gl_pthread_api=$gl_pthread_api" >&5
-      echo "$as_me:9813: LIBPTHREAD=$LIBPTHREAD" >&5
+      echo "$as_me:9865: gl_pthread_api=$gl_pthread_api" >&5
+      echo "$as_me:9866: LIBPTHREAD=$LIBPTHREAD" >&5
 
       gl_pthread_in_glibc=no
       # On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9836,7 +9889,7 @@ rm -rf conftest*
 
           ;;
       esac
-      echo "$as_me:9839: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
+      echo "$as_me:9892: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
 
       # Test for libpthread by looking for pthread_kill. (Not pthread_self,
       # since it is defined as a macro on OSF/1.)
@@ -10014,7 +10067,7 @@ fi
 
         fi
       fi
-      echo "$as_me:10017: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
+      echo "$as_me:10070: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
     fi
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
 printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -22804,6 +22857,53 @@ printf "%s\n" "$ac_cv_lib_tinfo_tgetent" >&6; }
 if test "x$ac_cv_lib_tinfo_tgetent" = xyes
 then :
   bash_cv_termcap_lib=libtinfo
+else case e in #(
+  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfow" >&5
+printf %s "checking for tgetent in -ltinfow... " >&6; }
+if test ${ac_cv_lib_tinfow_tgetent+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltinfow  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent (void);
+int
+main (void)
+{
+return tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_tinfow_tgetent=yes
+else case e in #(
+  e) ac_cv_lib_tinfow_tgetent=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfow_tgetent" >&5
+printf "%s\n" "$ac_cv_lib_tinfow_tgetent" >&6; }
+if test "x$ac_cv_lib_tinfow_tgetent" = xyes
+then :
+  bash_cv_termcap_lib=libtinfow
 else case e in #(
   e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
 printf %s "checking for tgetent in -lcurses... " >&6; }
@@ -22966,6 +23066,9 @@ esac
 fi
  ;;
 esac
+fi
+ ;;
+esac
 fi
 
 if test "X$_bash_needmsg" = "Xyes"; then
@@ -22984,6 +23087,9 @@ TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libtinfo; then
 TERMCAP_LIB=-ltinfo
 TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfow; then
+TERMCAP_LIB=-ltinfow
+TERMCAP_DEP=
 elif test $bash_cv_termcap_lib = libncursesw; then
 TERMCAP_LIB=-lncursesw
 TERMCAP_DEP=
index 2c6ea1c6d27d348dc65a06b2e87c459a049f82d8..cdb2e809ff2e0977549bdf7008e34b4513531d1b 100644 (file)
@@ -5,7 +5,7 @@
 .\"    Case Western Reserve University
 .\"    chet.ramey@case.edu
 .\"
-.\"    Last Change: Tue Jul 15 10:19:08 EDT 2025
+.\"    Last Change: Wed Jul 30 14:47:58 EDT 2025
 .\"
 .\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section
 .\" For rbash, strip all but "RESTRICTED SHELL" section
@@ -21,7 +21,7 @@
 .ds zY \" empty
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2025 July 15" "GNU Bash 5.3"
+.TH BASH 1 "2025 July 30" "GNU Bash 5.3"
 .\"
 .ie \n(.g \{\
 .ds ' \(aq
@@ -9260,6 +9260,7 @@ if \fIdir\fP is not supplied, the value of the
 .SM
 .B HOME
 shell variable is used as \fIdir\fP.
+If \fIdir\fP is the empty string, \fBcd\fP treats it as an error.
 The variable
 .SM
 .B CDPATH
index 22221df6cea8c5a17735bda5bb073acec1b0410b..32d70cda1a676d18eb37a08983c285db8e687212 100644 (file)
@@ -4241,6 +4241,7 @@ cd -P [-e] [-@@] [@var{directory}]
 Change the current working directory to @var{directory}.
 If @var{directory} is not supplied, the value of the @env{HOME}
 shell variable is used as @var{directory}.
+If @var{directory} is the empty string, @code{cd} treats it as an error.
 If the shell variable
 @env{CDPATH} exists,
 and @var{directory} does not begin with a slash,
index f0be321bdaa61408756464d9679accfb92f6783a..e8903e456d3003b71d54a50e2da633d97af68a44 100644 (file)
@@ -2,10 +2,10 @@
 Copyright (C) 1988-2025 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Sun May 18 13:42:18 EDT 2025
+@set LASTCHANGE Wed Jul 30 14:47:36 EDT 2025
 
 @set EDITION 5.3
 @set VERSION 5.3
 
-@set UPDATED 18 May 2025
-@set UPDATED-MONTH May 2025
+@set UPDATED 30 July 2025
+@set UPDATED-MONTH July 2025
index 070f5119317c52c5031909a88c5d04b6b14729a8..55e52b3e8c9769afc8dcea5f96120dfd0064e118 100644 (file)
@@ -5536,10 +5536,8 @@ execute_subshell_builtin_or_function (WORD_LIST *words, REDIRECT *redirects,
 
       if (result == EXITPROG || result == EXITBLTIN)
        subshell_exit (last_command_exit_value);
-#if 0  /* TAG:bash-5.4 https://savannah.gnu.org/support/?109840 6/5/2025 */
       else if (result == ERREXIT)
        subshell_exit (last_command_exit_value ? last_command_exit_value : EXECUTION_FAILURE);
-#endif
       else if (result)
        subshell_exit (EXECUTION_FAILURE);
       else if (funcvalue)
index a3a1f8b5a5b554336a08c0e6e493d5a3c24837e9..0293a7f70fff88c5e9ff6a7fadaf9316124bb9a9 100644 (file)
@@ -186,8 +186,18 @@ getcwd (char *buf, size_t size)
       dirstream = opendir (dotp);
       if (dirstream == NULL)
        goto lose;
-      while ((d = readdir (dirstream)) != NULL)
+      for (;;)
        {
+         errno = 0;
+         d = readdir (dirstream);
+
+         if (d == NULL)
+           {
+             if (errno == 0)
+               errno = ENOENT;
+             break;
+           }
+
          if (d->d_name[0] == '.' &&
              (d->d_name[1] == '\0' ||
                (d->d_name[1] == '.' && d->d_name[2] == '\0')))
@@ -208,27 +218,14 @@ getcwd (char *buf, size_t size)
              memcpy (&name[dotlist + dotsize - dotp + 1],
                      d->d_name, namlen + 1);
              if (lstat (name, &st) < 0)
-               {
-#if 0
-                 int save = errno;
-                 (void) closedir (dirstream);
-                 errno = save;
-                 goto lose;
-#else
-                 saved_errno = errno;
-#endif
-               }
+               saved_errno = errno;
              if (st.st_dev == thisdev && st.st_ino == thisino)
                break;
            }
        }
       if (d == NULL)
        {
-#if 0
-         int save = errno;
-#else
          int save = errno ? errno : saved_errno;
-#endif
          (void) closedir (dirstream);
          errno = save;
          goto lose;
diff --git a/po/stamp-po b/po/stamp-po
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/subst.c b/subst.c
index a8ae174d5da3854fa1c0cf1f98390f76a638ac5e..3849269df764872355dc73dd22ed0bcff81b5b35 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -11508,8 +11508,6 @@ add_string:
            }
        
        case '$':
-         if (expanded_something)
-           *expanded_something = 1;
          local_expanded = 1;
 
          temp_has_dollar_at = 0;
@@ -11521,12 +11519,15 @@ add_string:
          if (word->flags & W_COMPLETE)
            pflags |= PF_COMPLETE;
 
-         tword = param_expand (string, &sindex, quoted, expanded_something,
+         tword = param_expand (string, &sindex, quoted, &local_expanded,
                               &temp_has_dollar_at, &quoted_dollar_at,
                               &had_quoted_null, pflags);
          has_dollar_at += temp_has_dollar_at;
          split_on_spaces += (tword->flags & W_SPLITSPACE);
 
+         if (expanded_something)
+           *expanded_something |= local_expanded;
+
          if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
            {
              free (string);
@@ -11586,7 +11587,6 @@ add_string:
                
            if (expanded_something)
              *expanded_something = 1;
-           local_expanded = 1;
 
            if (word->flags & W_NOCOMSUB)
              /* sindex + 1 because string[sindex] == '`' */
@@ -11768,7 +11768,6 @@ add_twochars:
                    *contains_dollar_at = 1;
                  if (expanded_something)
                    *expanded_something = 1;
-                 local_expanded = 1;
                }
            }
          else