From: Chet Ramey Date: Mon, 4 Aug 2025 14:18:32 +0000 (-0400) Subject: fix for parameter expansions that contain valid and invalid expansions; avoid stale... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e9053f2a3ae4ed638d269481626e0e5408ae8965;p=thirdparty%2Fbash.git fix for parameter expansions that contain valid and invalid expansions; avoid stale readdir() value in getcwd replacement; check libtinfow for termcap functions; fix to propagate exit status of builtins run in subshells back to calling shell --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index bf82f2a3..44336651 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11476,8 +11476,42 @@ command.h - revert changes to COMMAND and SIMPLE_COM from 7/16 From a report by Jessica Clarke +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 + expr.c - expassign,expshift: avoid C23 undefined behavior when performing left and right arithmetic shifts From https://savannah.gnu.org/patch/?10532 bkallus + + 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 + + 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 + +aclocal.m4 + - BASH_CHECK_LIB_TERMCAP: add libtinfow to the library list to search + From a report by Дилян Палаузов + +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 diff --git a/aclocal.m4 b/aclocal.m4 index ae2d8aec..8d72b67e 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -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= diff --git a/builtins/cd.def b/builtins/cd.def index 5b39cb52..108862b8 100644 --- a/builtins/cd.def +++ b/builtins/cd.def @@ -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, diff --git a/configure b/configure index ccc7ea18..6288f0cb 100755 --- 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= diff --git a/doc/bash.1 b/doc/bash.1 index 2c6ea1c6..cdb2e809 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -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 diff --git a/doc/bashref.texi b/doc/bashref.texi index 22221df6..32d70cda 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -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, diff --git a/doc/version.texi b/doc/version.texi index f0be321b..e8903e45 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -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 diff --git a/execute_cmd.c b/execute_cmd.c index 070f5119..55e52b3e 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -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) diff --git a/lib/sh/getcwd.c b/lib/sh/getcwd.c index a3a1f8b5..0293a7f7 100644 --- a/lib/sh/getcwd.c +++ b/lib/sh/getcwd.c @@ -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 index 00000000..9788f702 --- /dev/null +++ b/po/stamp-po @@ -0,0 +1 @@ +timestamp diff --git a/subst.c b/subst.c index a8ae174d..3849269d 100644 --- 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, "ed_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