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