]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
avoid executing unsafe functions if we get a terminating signal while handling SIGCHL...
authorChet Ramey <chet.ramey@case.edu>
Tue, 20 Feb 2024 14:53:58 +0000 (09:53 -0500)
committerChet Ramey <chet.ramey@case.edu>
Tue, 20 Feb 2024 14:53:58 +0000 (09:53 -0500)
17 files changed:
CWRU/CWRU.chlog
MANIFEST
Makefile.in
arrayfunc.c
builtins/Makefile.in
builtins/declare.def
builtins/pushd.def
examples/loadables/necho.c
jobs.c
subst.c
subst.h
tests/array.right
tests/attr.right
tests/dollar-at-star
tests/dollar-star11.sub [new file with mode: 0644]
tests/dollar.right
variables.h

index 117fbd200c7c21ab25208a87bb25845c0a43dc37..e237bcdab8cf04137c2ca960e29a9081f77d338d 100644 (file)
@@ -8640,3 +8640,64 @@ MANIFEST
 lib/malloc/malloc.c,lib/malloc/table.h,lib/sh/strlcpy.c
        - fixes for ISO C 23
          Patch from Collin Funk <collin.funk1@gmail.com>
+
+                                  2/16
+                                  ----
+jobs.c
+       - waitchld: note whether or not we are executing in a signal handler
+         context and break out of the loop if we receive a terminating
+         signal instead of calling termsig_handler, which can execute unsafe
+         functions
+         From https://issues.redhat.com/browse/RHEL-22295
+
+variables.h
+       - valid_readonly_attrs,invalid_readonly_attrs: new defines for declare
+         to use to validate attempts to modify attributes of readonly
+         variables
+
+builtins/declare.def
+       - declare_internal: reject attempts to modify (set or unset) attributes 
+         in invalid_readonly_attrs for readonly variables.
+         From a discussion with Grisha Levit <grishalevit@gmail.com>
+
+                                  2/17
+                                  ----
+variables.h
+       - add att_readonly to valid_readonly_attrs; it's valid to use
+         declare -r var ; declare -r var
+
+Makefile.in,builtins/Makefile.in
+       - add unlocked-io.h to dependencies and variable contents where
+         appropriate
+       - add additional include files to INSTALLED_INCFILES
+
+builtins/pushd.def,examples/loadables/necho.c
+       - fix order of includes to get unlocked-io.h
+         From Grisha Levit <grishalevit@gmail.com>
+
+subst.c,subst.h
+       - rename quote_rhs -> quote_nosplit
+
+subst.c
+       - quote_var_value: break the code that quotes a variable value ($x,
+         ${x}, ${x[n]}, etc.) into a separate inline function and call it
+         from param_expand and parameter_brace_expand_word so they do it
+         consistently
+       - param_expand: quote $* appropriately using quote_nosplit if we are
+         in a place where word splitting will not occur (PF_NOSPLIT2),
+         expand_no_split_dollar_star == 1 but quoted is 0
+       - quote_var_value: use quote_nosplit if we are in a place where word
+         splitting will not occur (PF_NOSPLIT2) but quoted == 0.
+         Fixes bug with IFS=$'\1' reported by alex xmb sw ratchev <fxmbsw7@gmail.com>
+
+arrayfunc.c
+       - array_value: make sure to quote ${A[*]} appropriately if not quoted
+         (quoted == 0) and in a place where word splitting does not occur
+         (flags & AV_ASSIGNRHS); the caller expects array_value to quote in
+         this case
+
+subst.c
+       - parameter_brace_expand_word: make sure to call array_value with
+         AV_ASSIGNRHS if we are expanding unquoted ${A[*]} in a place where
+         word splitting does not occur with a non-null $IFS; array_value will
+         quote appropriately here
index 9f74b765e43f74518cd41a0d9bf14384bc500a14..5efab261dd1eec1d0b1a25c39c726e8a2b6d4668 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1129,6 +1129,7 @@ tests/dollar-star7.sub    f
 tests/dollar-star8.sub f
 tests/dollar-star9.sub f
 tests/dollar-star10.sub        f
+tests/dollar-star11.sub        f
 tests/dollar.right     f
 tests/dstack.tests     f
 tests/dstack.right     f
index 2f863e869eaae8b27aa64f80e8c27558d8e30fa6..41443c6de8c3093b1aa09532ae9a62e187032224 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile for bash-5.2, version 5.1
+# Makefile for bash-5.3, version 5.3
 #
 # Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
@@ -438,7 +438,11 @@ BASHINCFILES =      $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
                 $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
                 $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
                 $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
-                $(BASHINCDIR)/ocache.h
+                $(BASHINCDIR)/ocache.h $(BASHINCDIR)/unlocked-io.h \
+                $(BASHINCDIR)/chartypes.h \
+                $(BASHINCDIR)/gettext.h $(BASHINCDIR)/posixselect.h \
+                $(BASHINCDIR)/shmbchar.h $(BASHINCDIR)/shmbutil.h \
+                $(BASHINCDIR)/stat-time.h $(BASHINCDIR)/timer.h
 
 LIBRARIES = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) \
            $(TERMCAP_LIB) $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) \
@@ -487,7 +491,8 @@ INSTALLED_BUILTINS_HEADERS = bashgetopt.h common.h getopt.h
 INSTALLED_INCFILES =    posixstat.h ansi_stdlib.h filecntl.h posixdir.h \
        memalloc.h stdc.h posixjmp.h posixwait.h posixtime.h systimes.h \
        unionwait.h maxpath.h shtty.h typemax.h ocache.h chartypes.h gettext.h \
-       posixstat.h shmbchar.h shmbutil.h stat-time.h
+       posixstat.h shmbchar.h shmbutil.h stat-time.h posixselect.h \
+       timer.h unlocked-io.h
 
 # header files chosen based on running of configure
 SIGNAMES_H = @SIGNAMES_H@
@@ -1062,6 +1067,7 @@ copy_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
 copy_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 copy_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 copy_cmd.o: bashansi.h assoc.h $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h
+copy_cmd.o: $(BASHINCDIR)/unlocked-io.h
 dispose_cmd.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h
 dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1069,6 +1075,7 @@ dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 dispose_cmd.o: ${BASHINCDIR}/ocache.h
 dispose_cmd.o: assoc.h ${BASHINCDIR}/chartypes.h
+dispose_cmd.o: $(BASHINCDIR)/unlocked-io.h
 error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
 error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
 error.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
@@ -1077,12 +1084,14 @@ error.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 error.o: make_cmd.h subst.h sig.h pathnames.h externs.h execute_cmd.h
 error.o: input.h execute_cmd.h 
 error.o: $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h assoc.h
+error.o: $(BASHINCDIR)/unlocked-io.h
 eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
 eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
 eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h
 eval.o: input.h execute_cmd.h 
+eval.o: $(BASHINCDIR)/unlocked-io.h
 eval.o: bashhist.h assoc.h ${BASHINCDIR}/ocache.h ${BASHINCDIR}/chartypes.h
 execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
@@ -1096,6 +1105,7 @@ execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h
 execute_cmd.o: $(DEFSRC)/getopt.h
 execute_cmd.o: bashhist.h input.h ${GRAM_H} assoc.h hashcmd.h alias.h
 execute_cmd.o: ${BASHINCDIR}/ocache.h ${BASHINCDIR}/posixwait.h
+execute_cmd.o: $(BASHINCDIR)/unlocked-io.h
 expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h 
 expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1159,6 +1169,7 @@ mailcheck.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 mailcheck.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 mailcheck.o: execute_cmd.h mailcheck.h 
 mailcheck.o: ${BASHINCDIR}/ocache.h ${BASHINCDIR}/chartypes.h assoc.h
+mailcheck.o: $(BASHINCDIR)/unlocked-io.h
 make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
 make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
 make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
@@ -1176,6 +1187,7 @@ y.tab.o: trap.h flags.h parser.h input.h mailcheck.h $(DEFSRC)/common.h
 y.tab.o: $(DEFDIR)/builtext.h bashline.h bashhist.h jobs.h siglist.h alias.h
 y.tab.o: ${BASHINCDIR}/typemax.h assoc.h ${BASHINCDIR}/ocache.h
 y.tab.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h ${BASHINCDIR}/posixwait.h
+y.tab.o: $(BASHINCDIR)/unlocked-io.h
 pathexp.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 pathexp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 pathexp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1194,6 +1206,7 @@ print_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h
 print_cmd.o: flags.h input.h assoc.h
 print_cmd.o: $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h
+print_cmd.o: $(BASHINCDIR)/unlocked-io.h
 redir.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
 redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
@@ -1201,6 +1214,7 @@ redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
 redir.o: flags.h execute_cmd.h redir.h input.h
 redir.o: ${DEFDIR}/pipesize.h
 redir.o: trap.h assoc.h $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h
+redir.o: $(BASHINCDIR)/unlocked-io.h
 shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
 shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1210,6 +1224,7 @@ shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h
 shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h bashline.h
 shell.o: ${GLOB_LIBSRC}/strmatch.h ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/posixwait.h
 shell.o: ${BASHINCDIR}/ocache.h ${BASHINCDIR}/chartypes.h assoc.h alias.h
+shell.o: $(BASHINCDIR)/unlocked-io.h
 sig.o: config.h bashtypes.h
 sig.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 sig.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1217,6 +1232,7 @@ sig.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 sig.o: make_cmd.h subst.h sig.h pathnames.h externs.h execute_cmd.h
 sig.o: jobs.h siglist.h trap.h $(DEFSRC)/common.h bashline.h bashhist.h
 sig.o: ${DEFDIR}/builtext.h
+sig.o: $(BASHINCDIR)/unlocked-io.h
 siglist.o: config.h bashtypes.h siglist.h trap.h 
 stringlib.o: bashtypes.h ${BASHINCDIR}/chartypes.h
 stringlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
@@ -1236,6 +1252,7 @@ subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
 subst.o: ${BASHINCDIR}/chartypes.h
 subst.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 subst.o: ${DEFDIR}/builtext.h
+subst.o: $(BASHINCDIR)/unlocked-io.h
 test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1280,11 +1297,13 @@ jobs.o: jobs.h flags.h $(DEFSRC)/common.h $(DEFDIR)/builtext.h
 jobs.o: ${BASHINCDIR}/posixwait.h ${BASHINCDIR}/unionwait.h
 jobs.o: ${BASHINCDIR}/posixtime.h
 jobs.o: $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h $(BASHINCDIR)/typemax.h
+jobs.o: $(BASHINCDIR)/unlocked-io.h
 nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
 nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
 nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h parser.h
 nojobs.o: $(DEFDIR)/builtext.h
 nojobs.o: $(BASHINCDIR)/ocache.h $(BASHINCDIR)/chartypes.h $(BASHINCDIR)/typemax.h
+nojobs.o: $(BASHINCDIR)/unlocked-io.h
 
 # shell features that may be compiled in
 
@@ -1352,6 +1371,7 @@ pcomplete.o: externs.h ${BASHINCDIR}/maxpath.h execute_cmd.h
 pcomplete.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 pcomplete.o: builtins.h ${DEFDIR}/builtext.h ${DEFSRC}/common.h
 pcomplete.o: ${GLOB_LIBSRC}/glob.h ${GLOB_LIBSRC}/strmatch.h
+pcomplete.o: $(BASHINCDIR)/unlocked-io.h
 
 # library support files
 
@@ -1375,6 +1395,7 @@ bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
 bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
 bashline.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 bashline.o: ${DEFDIR}/builtext.h
+bashline.o: $(BASHINCDIR)/unlocked-io.h
 bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
 bracecomp.o: command.h ${BASHINCDIR}/stdc.h error.h
@@ -1489,6 +1510,7 @@ builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h
 builtins/common.o: execute_cmd.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h pathnames.h
 builtins/common.o: ${DEFDIR}/builtext.h parser.h
 builtins/common.o: ${BASHINCDIR}/chartypes.h
+builtins/common.o: $(BASHINCDIR)/unlocked-io.h
 builtins/evalfile.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 builtins/evalfile.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
 builtins/evalfile.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
@@ -1558,6 +1580,7 @@ builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwin
 builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/echo.o: pathnames.h
 builtins/echo.o: $(DEFSRC)/common.h
+builtins/echo.o: $(BASHINCDIR)/unlocked-io.h
 builtins/enable.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/enable.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
@@ -1578,6 +1601,7 @@ builtins/exit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwin
 builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/exit.o: pathnames.h execute_cmd.h
 builtins/exit.o: ${DEFDIR}/builtext.h
+builtins/exit.o: $(BASHINCDIR)/unlocked-io.h
 builtins/fc.o: bashtypes.h ${BASHINCDIR}/posixstat.h
 builtins/fc.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h builtins.h command.h ${BASHINCDIR}/stdc.h 
 builtins/fc.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
@@ -1585,6 +1609,7 @@ builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h
 builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h 
 builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h pathnames.h parser.h
 builtins/fc.o: ${BASHINCDIR}/chartypes.h
+builtins/fc.o: $(BASHINCDIR)/unlocked-io.h
 builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h 
 builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
@@ -1599,16 +1624,19 @@ builtins/hash.o: builtins.h command.h findcmd.h ${BASHINCDIR}/stdc.h $(DEFSRC)/c
 builtins/hash.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/hash.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
 builtins/hash.o: pathnames.h
+builtins/hash.o: $(BASHINCDIR)/unlocked-io.h
 builtins/help.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/help.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h
 builtins/help.o: conftypes.h quit.h execute_cmd.h
 builtins/help.o: $(GLOB_LIBSRC)/glob.h pathnames.h
+builtins/help.o: $(BASHINCDIR)/unlocked-io.h
 builtins/history.o: bashtypes.h pathnames.h parser.h
 builtins/history.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/history.o: ${BASHINCDIR}/filecntl.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h
 builtins/history.o: bashhist.h variables.h arrayfunc.h conftypes.h 
+builtins/history.o: $(BASHINCDIR)/unlocked-io.h
 builtins/inlib.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/inlib.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
 builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
@@ -1626,22 +1654,26 @@ builtins/let.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xm
 builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/let.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
 builtins/let.o: pathnames.h
+builtins/let.o: $(BASHINCDIR)/unlocked-io.h
 builtins/printf.o: config.h ${BASHINCDIR}/memalloc.h bashjmp.h command.h error.h
 builtins/printf.o: general.h xmalloc.h quit.h dispose_cmd.h make_cmd.h subst.h
 builtins/printf.o: externs.h sig.h pathnames.h shell.h syntax.h unwind_prot.h
 builtins/printf.o: variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/stdc.h $(DEFSRC)/bashgetopt.h
 builtins/printf.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 builtins/printf.o: ${BASHINCDIR}/chartypes.h 
+builtins/printf.o: $(BASHINCDIR)/unlocked-io.h
 builtins/pushd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/pushd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
 builtins/pushd.o: $(DEFSRC)/common.h pathnames.h
 builtins/pushd.o: ${DEFDIR}/builtext.h
+builtins/pushd.o: $(BASHINCDIR)/unlocked-io.h
 builtins/read.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/read.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
 builtins/read.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 builtins/read.o: pathnames.h
+builtins/read.o: $(BASHINCDIR)/unlocked-io.h
 builtins/return.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/return.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
@@ -1682,6 +1714,7 @@ builtins/times.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h
 builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/times.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
 builtins/times.o: pathnames.h
+builtins/times.o: $(BASHINCDIR)/unlocked-io.h
 builtins/trap.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/trap.o: quit.h $(DEFSRC)/common.h
 builtins/trap.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
index d56be4283d90286110085d4d87941344f055edb8..489caec96932eeca6d998466cc4de919a86934d8 100644 (file)
@@ -1555,6 +1555,12 @@ array_value_internal (const char *s, int quoted, int flags, array_eltstate_t *es
          retval = quote_string (temp);
          free (temp);
        }
+      else if (t[0] == '*' && quoted == 0 && (flags & AV_ASSIGNRHS))
+       {
+         temp = string_list_dollar_star (l, quoted, PF_ASSIGNRHS);
+         retval = quote_nosplit (temp);
+         free (temp);
+       }
       else     /* ${name[@]} or unquoted ${name[*]} */
        retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
 
index 642878c6c425790fd358168c23dd89e17b5268e3..86c7827fba97159eaaa9a6ce00eb31412d7764eb 100644 (file)
@@ -1,6 +1,6 @@
 # This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
 #
-# Copyright (C) 1996-2022 Free Software Foundation, Inc.
+# Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 #   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
@@ -343,6 +343,7 @@ common.o: $(topdir)/builtins.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 common.o: $(topdir)/subst.h $(topdir)/execute_cmd.h $(topdir)/error.h
 common.o: $(topdir)/externs.h ../pathnames.h ./builtext.h
 common.o: $(BASHINCDIR)/chartypes.h
+common.o: $(BASHINCDIR)/unlocked-io.h
 evalfile.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h ${BASHINCDIR}/filecntl.h
 evalfile.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
 evalfile.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h
@@ -439,6 +440,7 @@ echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/
 echo.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 echo.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
 echo.o: $(srcdir)/common.h
+echo.o: $(BASHINCDIR)/unlocked-io.h
 enable.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 enable.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 enable.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -468,6 +470,7 @@ exit.o: $(topdir)/subst.h $(topdir)/externs.h  $(topdir)/jobs.h
 exit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 exit.o: $(topdir)/execute_cmd.h
 exit.o: $(BASHINCDIR)/maxpath.h ./builtext.h ../pathnames.h
+exit.o: $(BASHINCDIR)/unlocked-io.h
 fc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
 fc.o: $(topdir)/builtins.h $(topdir)/command.h $(srcdir)/bashgetopt.h
 fc.o: $(topdir)/bashhist.h $(topdir)/parser.h
@@ -478,6 +481,7 @@ fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h $(topdir)/syntax.h
 fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 fc.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h $(BASHINCDIR)/chartypes.h
 fc.o: ../pathnames.h
+fc.o: $(BASHINCDIR)/unlocked-io.h
 fg_bg.o: $(topdir)/bashtypes.h $(srcdir)/bashgetopt.h
 fg_bg.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
@@ -498,6 +502,7 @@ hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h $(topdir)/sig.h
 hash.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 hash.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 hash.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h
+hash.o: $(BASHINCDIR)/unlocked-io.h
 hash.o: $(topdir)/conftypes.h $(topdir)/execute_cmd.h
 hash.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
 help.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
@@ -507,6 +512,7 @@ help.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 help.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h
 help.o: $(topdir)/conftypes.h $(topdir)/execute_cmd.h
 help.o: ${srcdir}/common.h $(topdir)/sig.h ../pathnames.h
+help.o: $(BASHINCDIR)/unlocked-io.h
 history.o: $(topdir)/bashtypes.h
 history.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 history.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
@@ -515,6 +521,7 @@ history.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h  $(topdir)/pars
 history.o: ${BASHINCDIR}/filecntl.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
 history.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/bashhist.h $(BASHINCDIR)/maxpath.h
 history.o: ../pathnames.h
+history.o: $(BASHINCDIR)/unlocked-io.h
 inlib.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 inlib.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 inlib.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
@@ -538,6 +545,7 @@ let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/s
 let.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 let.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 let.o: ../pathnames.h
+let.o: $(BASHINCDIR)/unlocked-io.h
 printf.o: ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/bashjmp.h
 printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -547,6 +555,7 @@ printf.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/stdc.h $(src
 printf.o: $(topdir)/bashtypes.h ${srcdir}/common.h $(BASHINCDIR)/chartypes.h
 printf.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 printf.o: ../pathnames.h
+printf.o: $(BASHINCDIR)/unlocked-io.h
 pushd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 pushd.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -554,6 +563,7 @@ pushd.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h
 pushd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 pushd.o: $(BASHINCDIR)/maxpath.h $(srcdir)/common.h ./builtext.h
 pushd.o: ../pathnames.h
+pushd.o: $(BASHINCDIR)/unlocked-io.h
 read.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 read.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 read.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -562,6 +572,7 @@ read.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/v
 read.o: $(BASHINCDIR)/shtty.h $(topdir)/sig.h
 read.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
 read.o: $(topdir)/arrayfunc.h ../pathnames.h
+read.o: $(BASHINCDIR)/unlocked-io.h
 return.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 return.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 return.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/sig.h
@@ -622,6 +633,7 @@ times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)
 times.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 times.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 times.o: $(BASHINCDIR)/posixtime.h ../pathnames.h
+times.o: $(BASHINCDIR)/unlocked-io.h
 trap.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
 trap.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h $(topdir)/sig.h
index ed910d577d6d1531359bbebba55a2a741696eee5..cacf286c9ea89c9ee376c34b31f2e66999e55c7d 100644 (file)
@@ -672,6 +672,10 @@ restart_new_var_name:
              any_failed++;
              NEXT_VARIABLE ();
            }
+         /* See below; ksh93 doesn't allow the nameref attribute to be removed
+            from a readonly nameref that has a value, even if it doesn't
+            reference an existing variable, so we don't allow it for
+            compatibility. */
          if (var && nameref_p (var) && readonly_p (var) && nameref_cell (var) && (flags_off & att_nameref))
            {
              sh_readonly (name);
@@ -711,7 +715,7 @@ restart_new_var_name:
          if (refvar && nameref_p (refvar) == 0)
            refvar = 0;
          /* If the nameref is readonly but doesn't have a value, ksh93
-            allows the nameref attribute to be removed.  If it's readonly
+            allows the nameref attribute to be removed. If it's readonly
             and has a value, even if the value doesn't reference an
             existing variable, we disallow the modification */
          if (refvar && nameref_cell (refvar) && readonly_p (refvar))
@@ -886,6 +890,18 @@ restart_new_var_name:
             EXECUTION_FAILURE would cause set -e to exit the shell. */
          NEXT_VARIABLE ();
        }
+#if 1
+      /* TAG:bash-5.3 20240216 */
+      /* Cannot set or unset invalid attributes on readonly variables */
+      else if (readonly_p (var) && ((flags_on & invalid_readonly_attrs) || (flags_off & invalid_readonly_attrs)))
+       {
+         /* The restrictions on namerefs and readonly variables are handled
+            above. */
+         sh_readonly (name_cell (var));
+         any_failed++;
+         NEXT_VARIABLE ();
+       }
+#endif
 
 #if defined (ARRAY_VARS)
       /* Array variable error checking. */
index d0625e3d6c222e0a36342b7ae8ed0287fd9d5c18..b3a6f5d37c56a475f5bb04a8dae88b1bd9a90b7d 100644 (file)
@@ -1,7 +1,7 @@
 This file is pushd.def, from which is created pushd.c.  It implements the
 builtins "pushd", "popd", and "dirs" in Bash.
 
-Copyright (C) 1987-2023 Free Software Foundation, Inc.
+Copyright (C) 1987-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -116,6 +116,10 @@ $END
 #include <config.h>
 
 #if defined (PUSHD_AND_POPD)
+#ifdef LOADABLE_BUILTIN
+#  include "builtins.h"
+#endif
+
 #include <stdio.h>
 #if defined (HAVE_SYS_PARAM_H)
 #  include <sys/param.h>
@@ -140,10 +144,6 @@ $END
 #include "common.h"
 #include "builtext.h"
 
-#ifdef LOADABLE_BUILTIN
-#  include "builtins.h"
-#endif
-
 #if !defined (errno)
 extern int errno;
 #endif /* !errno */
index 463866741fb1f8188ba31d93e30502349a2f5fbb..3ad677c4fce31fa5611becafc3d0eb531e48b413 100644 (file)
    You should have received a copy of the GNU General Public License
    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 */
+#include <config.h>
 
-#include <stdio.h>
 #include "builtins.h"
 #include "shell.h"
+#include <stdio.h>
 
 int
 necho_builtin (WORD_LIST *list)
diff --git a/jobs.c b/jobs.c
index caafa734a5b7157c221b3c0728b2da251939aa2f..7b30a0ce30747b4201c27e552c46247989a73dc6 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -3778,7 +3778,7 @@ waitchld (pid_t wpid, int block)
   WAIT status;
   PROCESS *child;
   pid_t pid;
-  int ind;
+  int ind, sighandler_context;
 
   int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
   static int wcontinued = WCONTINUED;  /* run-time fix for glibc problem */
@@ -3786,6 +3786,9 @@ waitchld (pid_t wpid, int block)
   call_set_current = children_exited = 0;
   last_stopped_job = NO_JOB;
 
+  /* We save this because we modify sigchld below */
+  sighandler_context = sigchld != 0;
+
   do
     {
       /* We don't want to be notified about jobs stopping if job control
@@ -3797,6 +3800,8 @@ waitchld (pid_t wpid, int block)
        waitpid_flags |= WNOHANG;
 
       /* Check for terminating signals and exit the shell if we receive one */
+      if (sighandler_context && terminating_signal)
+       break;
       CHECK_TERMSIG;
       /* Check for a trapped signal interrupting the wait builtin and jump out */
       CHECK_WAIT_INTR;
@@ -3844,6 +3849,8 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc
 #endif
       /* If waitpid returns 0, there are running children.  If it returns -1,
         the only other error POSIX says it can return is EINTR. */
+      if (sighandler_context && terminating_signal)
+       break;
       CHECK_TERMSIG;
       CHECK_WAIT_INTR;
 
@@ -3981,7 +3988,7 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc
      that has just changed state.  If we notify asynchronously, and the job
      that this process belongs to is no longer running, then notify the user
      of that fact now. */
-  if (asynchronous_notification && interactive && executing_builtin == 0)
+  if (children_exited && asynchronous_notification && interactive && executing_builtin == 0)
     notify_of_job_status ();
 
   return (children_exited);
diff --git a/subst.c b/subst.c
index d4ad52afd15151d05b2f3cd68d12204e8a4c8e86..1bf2ea296efbb59484b97982f3fde3cb03a855f2 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4651,7 +4651,7 @@ quote_escapes (const char *string)
 }
 
 char *
-quote_rhs (const char *string)
+quote_nosplit (const char *string)
 {
   return (quote_escapes_internal (string, PF_NOSPLIT2));
 }
@@ -5002,6 +5002,31 @@ word_list_remove_quoted_nulls (WORD_LIST *list)
     }
 }
 
+/* Quote TEMP appropriately using CTLESC. TEMP is a variable value ($x,
+   ${x[a]}, etc.). This is used in param_expand and parameter_brace_expand_word */
+static inline char *
+quote_var_value (char *temp, int quoted, int pflags)
+{
+  char *ret;
+
+  if (temp == 0)
+    ret = temp;
+  else if (*temp == 0)
+    ret = savestring ("");     /* QUOTED_NULL later */
+  else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+    ret = quote_string (temp);
+  else if (pflags & PF_ASSIGNRHS)
+    ret = quote_nosplit (temp);
+  else if (expand_no_split_dollar_star && quoted == 0 && (pflags & PF_NOSPLIT2) && ifs_is_set && ifs_is_null == 0)
+    /* This test might be too specific; we only want to quote CTLESC
+       in IFS under specific circumstances */
+    ret = quote_nosplit (temp);        /* XXX */
+  else
+    ret = quote_escapes (temp);
+
+  return ret;
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*        Functions for Matching and Removing Patterns             */
@@ -7395,6 +7420,8 @@ command_substitute (char *string, int quoted, int flags)
        kill (getpid (), SIGINT);
 #endif /* JOB_CONTROL */
 
+      CHECK_TERMSIG;
+
       ret = alloc_word_desc ();
       ret->word = istring;
       ret->flags = tflag;
@@ -7665,6 +7692,8 @@ expand_arrayref:
            temp = array_value (name, quoted, 0, &es);
          else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_null)
            temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &es);
+         else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_set && ifs_is_null == 0 && quoted == 0)
+           temp = array_value (name, quoted, AV_ASSIGNRHS, &es);
          else if (tt[0] == '*' && tt[1] == RBRACK)
            temp = array_value (name, quoted, 0, &es);
          else
@@ -7676,9 +7705,7 @@ expand_arrayref:
        temp = array_value (name, quoted, 0, &es);
       if (es.subtype == 0 && temp)
        {
-         temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-                   ? quote_string (temp)
-                   : quote_escapes (temp);
+         temp = quote_var_value (temp, quoted, pflags);
          rflags |= W_ARRAYIND;
        }
       /* Note that array[*] and array[@] expanded to a quoted null string by
@@ -7712,16 +7739,11 @@ expand_arrayref:
          else if (array_p (var))
            temp = array_reference (array_cell (var), 0);
          else
-           temp = value_cell (var);
-#else
-         temp = value_cell (var);
 #endif
+           temp = value_cell (var);
+
+         temp = quote_var_value (temp, quoted, pflags);
 
-         if (temp)
-           temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-                     ? quote_string (temp)
-                     : ((pflags & PF_ASSIGNRHS) ? quote_rhs (temp)
-                                                : quote_escapes (temp));
          FREE (tt);
        }
       else
@@ -10552,6 +10574,18 @@ param_expand (char *string, size_t *sindex, int quoted,
              temp1 = string_list_dollar_star (list, quoted, pflags);
              temp = temp1 ? quote_string (temp1) : temp1;
 
+             /* XXX - tentative - note that we saw a quoted null here */
+             if (temp1 && *temp1 == 0 && QUOTED_NULL (temp))
+               tflag |= W_SAWQUOTEDNULL;
+             FREE (temp1);
+           }
+         else if (expand_no_split_dollar_star && quoted == 0 && ifs_is_set && ifs_is_null == 0 && (pflags & PF_NOSPLIT2))
+           {
+             /* no splitting (conditional command, pattern expansion, array
+                subscripts, case command word), IFS set to non-null value */
+             temp1 = string_list_dollar_star (list, quoted, 0);
+             temp = temp1 ? quote_nosplit (temp1) : temp1;
+
              /* XXX - tentative - note that we saw a quoted null here */
              if (temp1 && *temp1 == 0 && QUOTED_NULL (temp))
                tflag |= W_SAWQUOTEDNULL;
@@ -10864,26 +10898,18 @@ comsub:
        {
 #if defined (ARRAY_VARS)
          if (assoc_p (var) || array_p (var))
-           {
-             temp = array_p (var) ? array_reference (array_cell (var), 0)
-                                  : assoc_reference (assoc_cell (var), "0");
-             if (temp)
-               temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-                         ? quote_string (temp)
-                         : quote_escapes (temp);
-             else if (unbound_vars_is_error)
-               goto unbound_variable;
-           }
+           temp = array_p (var) ? array_reference (array_cell (var), 0)
+                                : assoc_reference (assoc_cell (var), "0");
          else
 #endif
-           {
-             temp = value_cell (var);
+           /* $X */
+           temp = value_cell (var);
 
-             temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-                       ? quote_string (temp)
-                       : ((pflags & PF_ASSIGNRHS) ? quote_rhs (temp)
-                                                  : quote_escapes (temp));
-           }
+         /* Quote the value appropriately */
+         if (temp == 0 && unbound_vars_is_error)
+           goto unbound_variable;
+         else
+           temp = quote_var_value (temp, quoted, pflags);
 
          free (temp1);
 
diff --git a/subst.h b/subst.h
index 2117e7ccc85fd164b37255cdecd006762fab32ae..6c20978fcbbf32fcf7f6d1ce4856a5f79ba995d8 100644 (file)
--- a/subst.h
+++ b/subst.h
@@ -1,6 +1,6 @@
 /* subst.h -- Names of externally visible functions in subst.c. */
 
-/* Copyright (C) 1993-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -243,8 +243,9 @@ extern char *quote_escapes (const char *);
 /* And remove such quoted special characters. */
 extern char *remove_quoted_escapes (char *);
 
-/* Quote escape characters on the rhs of a word expansion. */
-extern char *quote_rhs (const char *);
+/* Quote escape characters in contexts where word splitting won't be
+   performed, e.g.,  on the rhs of a word expansion. */
+extern char *quote_nosplit (const char *);
 
 /* Remove CTLNUL characters from STRING unless they are quoted with CTLESC. */
 extern char *remove_quoted_nulls (char *);
index 346557a1838e9191914481bbb7d09d4428cc4566..5da194a6b026cde433536a0e9ea91461f7ce1ce0 100644 (file)
@@ -70,7 +70,7 @@ declare -a d=([1]="test test")
 declare -a e=()
 declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element")
 ./array.tests: line 137: unset: ps1: not an array variable
-./array.tests: line 141: declare: c: cannot destroy array variables in this way
+./array.tests: line 141: declare: c: readonly variable
 this of
 this is a test of read using arrays
 this test
index d2d28b7b41f4f31178b182478fa4446ee75b4c96..f4c3010cde932a37dc05094e9d4d631b7db13bab 100644 (file)
@@ -1,5 +1,5 @@
 after f1:declare -ar a=([0]="1")
-./attr.tests: line 17: a: readonly variable
+./attr.tests: line 17: f2: a: readonly variable
 after f2:declare -ar a=([0]="1")
 ./attr.tests: line 18: a: readonly variable
 after f3:declare -ar a=([0]="1")
@@ -17,7 +17,7 @@ declare -r p="1"
 declare -ar r=([0]="1")
 ./attr1.sub: line 36: r: readonly variable
 declare -ar r=([0]="1")
-./attr1.sub: line 40: r: readonly variable
+./attr1.sub: line 40: f: r: readonly variable
 declare -ar r=([0]="1")
 ./attr1.sub: line 44: readonly: r: readonly variable
 declare -ar r=([0]="1")
index 721eea124c7b7f64835a5ce16cd3e4bd0d648e85..e7b24eed44f51b67dde255827139f2097ec7cc17 100755 (executable)
@@ -329,4 +329,7 @@ ${THIS_SH} ./dollar-star9.sub
 # null strings as the positional parameters
 ${THIS_SH} ./dollar-star10.sub
 
+# tests for expansions of $* when IFS=$'\1'
+${THIS_SH} ./dollar-star11.sub
+
 exit 0
diff --git a/tests/dollar-star11.sub b/tests/dollar-star11.sub
new file mode 100644 (file)
index 0000000..25d30be
--- /dev/null
@@ -0,0 +1,43 @@
+set aa bb cc -- dd ; f=$'\1' IFS=$f
+
+recho "$f$*$f"
+recho "$f--$f"
+
+[[ $f$*$f == *$f--$f* ]] && echo ok 1
+[[ $f$*$f == "$f--$f" ]] || echo ok 2
+
+[[ ${f}${*}${f} == *$f--$f* ]] && echo ok 3
+
+[[ $f$*$f == $f$*$f ]] && echo ok 4
+[[ ${f}${*}${f} == $f$*$f ]] && echo ok 5
+[[ $f$*$f == *--* ]] && echo ok 6
+
+[[ $* == $* ]] && echo ok 7
+[[ $* == ${*} ]] && echo ok 8
+[[ $f == $f ]] && echo ok 9
+[[ $f == ${f} ]] && echo ok 10
+
+# now with f an array and $f -> ${f[0]}
+
+set aa bb cc -- dd ; f=( $'\1' )
+
+[[ $f$*$f == *$f--$f* ]] && echo ok 11
+[[ ${f}${*}${f} == *$f--$f* ]] && echo ok 12
+[[ $f$*$f == $f$*$f ]] && echo ok 13
+[[ ${f}${*}${f} == $f$*$f ]] && echo ok 14
+[[ $f$*$f == *--* ]] && echo ok 15
+
+[[ $* == $* ]] && echo ok 16
+[[ $* == ${*} ]] && echo ok 17
+[[ $f == $f ]] && echo ok 18
+[[ $f == ${f} ]] && echo ok 19
+
+# now use an array instead of $*
+A=( aa bb cc -- dd ); f=$'\1' IFS=$f
+
+[[ $f${A[*]}$f == $f${A[*]}$f ]] && echo ok 20
+[[ $f${A[*]}$f == *--* ]] && echo ok 21
+[[ ${f}${A[*]}${f} == *$f--$f* ]] && echo ok 22
+
+[[ ${f}${A[*]}${f} == $f${A[*]}$f ]] && echo ok 23
+[[ ${A[*]} == ${A[*]} ]] && echo ok 24
index 10c5cca13fdef331f00778bbe2acedc891bb22bd..7041fd37620eadcef514cc5fe9c7d30842392670 100644 (file)
@@ -742,3 +742,29 @@ argv[2] = <2>
 var=1 2
 argv[1] = <1 2>
 argv[1] = <1 2>
+argv[1] = <^Aaa^Abb^Acc^A--^Add^A>
+argv[1] = <^A--^A>
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+ok 7
+ok 8
+ok 9
+ok 10
+ok 11
+ok 12
+ok 13
+ok 14
+ok 15
+ok 16
+ok 17
+ok 18
+ok 19
+ok 20
+ok 21
+ok 22
+ok 23
+ok 24
index 29662ab2d24a4c52df9eabf58f44255d08ecdd23..3d66fa21fba261eb4341cc9b83baa7aa488a9119 100644 (file)
@@ -115,9 +115,17 @@ typedef struct _vlist {
 #define att_capcase    0x0000400       /* word capitalized on assignment */
 #define att_nameref    0x0000800       /* word is a name reference */
 
+#define attmask_user   0x0000fff
+
 #define user_attrs     (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase|att_nameref)
 
-#define attmask_user   0x0000fff
+/* These define attributes you can set on readonly variables using declare.
+   You're allowed to set the readonly attribute on a readonly variable.
+   declare checks whether it gets +r explicitly, before testing these.
+   att_nameref is in there because declare performs its own validation due
+   to some ksh93 quirks. */
+#define valid_readonly_attrs   (att_exported|att_local|att_nameref|att_trace|att_readonly)
+#define invalid_readonly_attrs (~valid_readonly_attrs & attmask_user)
 
 /* Internal attributes used for bookkeeping */
 #define att_invisible  0x0001000       /* cannot see */