From: Chet Ramey Date: Tue, 20 Feb 2024 14:53:58 +0000 (-0500) Subject: avoid executing unsafe functions if we get a terminating signal while handling SIGCHL... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cc51fb3c6521781b4e0cc3fbbffcc8bf746e9c25;p=thirdparty%2Fbash.git avoid executing unsafe functions if we get a terminating signal while handling SIGCHLD; reject attempts to modify some attributes for readonly variables; more changes for unlocked stdio functions; quoting fixes for uncommon cases where IFS = ^A and the word is not being split --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 117fbd200..e237bcdab 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -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 + + 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 + + 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 + +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 + +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 diff --git a/MANIFEST b/MANIFEST index 9f74b765e..5efab261d 100644 --- 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 diff --git a/Makefile.in b/Makefile.in index 2f863e869..41443c6de 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/arrayfunc.c b/arrayfunc.c index d56be4283..489caec96 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -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); diff --git a/builtins/Makefile.in b/builtins/Makefile.in index 642878c6c..86c7827fb 100644 --- a/builtins/Makefile.in +++ b/builtins/Makefile.in @@ -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 diff --git a/builtins/declare.def b/builtins/declare.def index ed910d577..cacf286c9 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -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. */ diff --git a/builtins/pushd.def b/builtins/pushd.def index d0625e3d6..b3a6f5d37 100644 --- a/builtins/pushd.def +++ b/builtins/pushd.def @@ -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 #if defined (PUSHD_AND_POPD) +#ifdef LOADABLE_BUILTIN +# include "builtins.h" +#endif + #include #if defined (HAVE_SYS_PARAM_H) # include @@ -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 */ diff --git a/examples/loadables/necho.c b/examples/loadables/necho.c index 463866741..3ad677c4f 100644 --- a/examples/loadables/necho.c +++ b/examples/loadables/necho.c @@ -20,10 +20,11 @@ You should have received a copy of the GNU General Public License along with Bash. If not, see . */ +#include -#include #include "builtins.h" #include "shell.h" +#include int necho_builtin (WORD_LIST *list) diff --git a/jobs.c b/jobs.c index caafa734a..7b30a0ce3 100644 --- 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 d4ad52afd..1bf2ea296 100644 --- 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 2117e7ccc..6c20978fc 100644 --- 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 *); diff --git a/tests/array.right b/tests/array.right index 346557a18..5da194a6b 100644 --- a/tests/array.right +++ b/tests/array.right @@ -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 diff --git a/tests/attr.right b/tests/attr.right index d2d28b7b4..f4c3010cd 100644 --- a/tests/attr.right +++ b/tests/attr.right @@ -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") diff --git a/tests/dollar-at-star b/tests/dollar-at-star index 721eea124..e7b24eed4 100755 --- a/tests/dollar-at-star +++ b/tests/dollar-at-star @@ -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 index 000000000..25d30be02 --- /dev/null +++ b/tests/dollar-star11.sub @@ -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 diff --git a/tests/dollar.right b/tests/dollar.right index 10c5cca13..7041fd376 100644 --- a/tests/dollar.right +++ b/tests/dollar.right @@ -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 diff --git a/variables.h b/variables.h index 29662ab2d..3d66fa21f 100644 --- a/variables.h +++ b/variables.h @@ -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 */