unconditionally define PGRP_PIPE; fix wait in funsubs; fix REPLY as nameref in varsub; fix crash with parse errors in compound assignments

This commit is contained in:
Chet Ramey
2024-01-14 15:38:36 -05:00
parent 584a2b4c9e
commit f2fdb5e313
14 changed files with 125 additions and 154 deletions
+44
View File
@@ -8260,3 +8260,47 @@ parse.y
reset_parser already freed it and we don't want to try and restore
it in restore_parser_state.
From a report by Nathan Mills <the.true.nathan.mills@gmail.com>
1/10
----
builtins/hash.def, builtins/ulimit.def
- add some calls to sh_chkwrite where there is builtin output
lib/sh/eaccess.c
- sh_stat: use strcpy/strcpy when constructing pbuf instead of
strcpy/strcat
lib/sh/tmpfile.c
- sh_mktmpname,sh_mktmpfd,sh_mktmpdir: use snprintf (filename, PATH_MAX, ...)
instead of sprintf (filename, ...)
1/11
----
configure.ac
- unconditionally AC_DEFINE(PGRP_PIPE), to prevent the problem with a
pipeline and a DEBUG trap containing an external command described
in https://lists.gnu.org/archive/html/bug-bash/2024-01/msg00037.html
1/12
----
jobs.c
- wait_for_any_job: if we're executing a funsub/varsub, do the wait
even if the jobs list is frozen, but don't remove the job from the
table or change its notification status
Report from Oguz <oguzismailuysal@gmail.com>
subst.c
- uw_unbind_variable: unset the first instance of the named variable,
don't follow namerefs. This is for REPLY in a varsub if it's made
a nameref.
Report from Oguz <oguzismailuysal@gmail.com>
shell.c
- main: call compat_init() so the linker drags in the old compatibility
functions from lib/sh/compat.c. Primarily for use by existing loadable
builtins
parse.y
- parse_compound_assignment: handle error case (wl == &parse_string_error)
before restoring the parser state from ps
Report from Grisha Levit <grishalevit@gmail.com>
+2 -2
View File
@@ -123,7 +123,7 @@ hash_builtin (WORD_LIST *list)
if (list == 0 && (delete || list_targets))
{
sh_needarg (delete ? "-d" : "-t");
return (EXECUTION_FAILURE);
return (sh_chkwrite (EXECUTION_FAILURE));
}
/* It's an error to specify a pathname to hash to, but no name to hash. */
@@ -299,5 +299,5 @@ list_hashed_filename_targets (WORD_LIST *list, int fmt)
free (target);
}
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
return (sh_chkwrite (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE));
}
+1 -1
View File
@@ -437,7 +437,7 @@ ulimit_builtin (WORD_LIST *list)
if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
return (EXECUTION_FAILURE);
return (EXECUTION_SUCCESS);
return (sh_chkwrite (EXECUTION_SUCCESS));
}
static int
Vendored
+34 -127
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.ac for Bash 5.3, version 5.059.
# From configure.ac for Bash 5.3, version 5.060.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for bash 5.3-devel.
#
@@ -8454,21 +8454,19 @@ $ac_includes_default
VM page cache was not coherent with the file system buffer cache
like early versions of FreeBSD and possibly contemporary NetBSD.)
For shared mappings, we should conversely verify that changes get
propagated back to all the places they're supposed to be.
Grep wants private fixed already mapped.
The main things grep needs to know about mmap are:
* does it exist and is it safe to write into the mmap'd area
* how to use it (BSD variants) */
propagated back to all the places they're supposed to be. */
#include <fcntl.h>
#include <sys/mman.h>
/* This mess was copied from the GNU getpagesize.h. */
#ifndef HAVE_GETPAGESIZE
#ifndef getpagesize
# ifdef _SC_PAGESIZE
# define getpagesize() sysconf(_SC_PAGESIZE)
# else /* no _SC_PAGESIZE */
# define getpagesize() sysconf (_SC_PAGESIZE)
# elif defined _SC_PAGE_SIZE
# define getpagesize() sysconf (_SC_PAGE_SIZE)
# elif HAVE_GETPAGESIZE
int getpagesize ();
# else
# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# ifdef EXEC_PAGESIZE
@@ -8492,16 +8490,15 @@ $ac_includes_default
# else /* no HAVE_SYS_PARAM_H */
# define getpagesize() 8192 /* punt totally */
# endif /* no HAVE_SYS_PARAM_H */
# endif /* no _SC_PAGESIZE */
#endif /* no HAVE_GETPAGESIZE */
# endif
#endif
int
main (void)
{
char *data, *data2, *data3;
const char *cdata2;
int i, pagesize;
long i, pagesize;
int fd, fd2;
pagesize = getpagesize ();
@@ -9058,8 +9055,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
echo "$as_me:9061: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9062: LIBPTHREAD=$LIBPTHREAD" >&5
echo "$as_me:9058: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9059: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9085,7 +9082,7 @@ rm -rf conftest*
;;
esac
echo "$as_me:9088: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
echo "$as_me:9085: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
# Test for libpthread by looking for pthread_kill. (Not pthread_self,
# since it is defined as a macro on OSF/1.)
@@ -9239,7 +9236,7 @@ fi
fi
fi
echo "$as_me:9242: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
echo "$as_me:9239: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -9467,8 +9464,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
echo "$as_me:9470: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9471: LIBPTHREAD=$LIBPTHREAD" >&5
echo "$as_me:9467: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9468: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9494,7 +9491,7 @@ rm -rf conftest*
;;
esac
echo "$as_me:9497: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
echo "$as_me:9494: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
# Test for libpthread by looking for pthread_kill. (Not pthread_self,
# since it is defined as a macro on OSF/1.)
@@ -9648,7 +9645,7 @@ fi
fi
fi
echo "$as_me:9651: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
echo "$as_me:9648: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -16302,21 +16299,19 @@ $ac_includes_default
VM page cache was not coherent with the file system buffer cache
like early versions of FreeBSD and possibly contemporary NetBSD.)
For shared mappings, we should conversely verify that changes get
propagated back to all the places they're supposed to be.
Grep wants private fixed already mapped.
The main things grep needs to know about mmap are:
* does it exist and is it safe to write into the mmap'd area
* how to use it (BSD variants) */
propagated back to all the places they're supposed to be. */
#include <fcntl.h>
#include <sys/mman.h>
/* This mess was copied from the GNU getpagesize.h. */
#ifndef HAVE_GETPAGESIZE
#ifndef getpagesize
# ifdef _SC_PAGESIZE
# define getpagesize() sysconf(_SC_PAGESIZE)
# else /* no _SC_PAGESIZE */
# define getpagesize() sysconf (_SC_PAGESIZE)
# elif defined _SC_PAGE_SIZE
# define getpagesize() sysconf (_SC_PAGE_SIZE)
# elif HAVE_GETPAGESIZE
int getpagesize ();
# else
# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# ifdef EXEC_PAGESIZE
@@ -16340,16 +16335,15 @@ $ac_includes_default
# else /* no HAVE_SYS_PARAM_H */
# define getpagesize() 8192 /* punt totally */
# endif /* no HAVE_SYS_PARAM_H */
# endif /* no _SC_PAGESIZE */
#endif /* no HAVE_GETPAGESIZE */
# endif
#endif
int
main (void)
{
char *data, *data2, *data3;
const char *cdata2;
int i, pagesize;
long i, pagesize;
int fd, fd2;
pagesize = getpagesize ();
@@ -18473,96 +18467,6 @@ printf "%s\n" "#define DUP2_BROKEN 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pgrps need synchronization" >&5
printf %s "checking whether pgrps need synchronization... " >&6; }
if test ${bash_cv_pgrp_pipe+y}
then :
printf %s "(cached) " >&6
else $as_nop
if test "$cross_compiling" = yes
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot check pgrp synchronization if cross compiling -- defaulting to no" >&5
printf "%s\n" "$as_me: WARNING: cannot check pgrp synchronization if cross compiling -- defaulting to no" >&2;}
bash_cv_pgrp_pipe=no
else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#include <stdlib.h>
int
main()
{
# ifdef GETPGRP_VOID
# define getpgID() getpgrp()
# else
# define getpgID() getpgrp(0)
# define setpgid(x,y) setpgrp(x,y)
# endif
int pid1, pid2, fds[2];
int status;
char ok;
switch (pid1 = fork()) {
case -1:
exit(1);
case 0:
setpgid(0, getpid());
exit(0);
}
setpgid(pid1, pid1);
sleep(2); /* let first child die */
if (pipe(fds) < 0)
exit(2);
switch (pid2 = fork()) {
case -1:
exit(3);
case 0:
setpgid(0, pid1);
ok = getpgID() == pid1;
write(fds[1], &ok, 1);
exit(0);
}
setpgid(pid2, pid1);
close(fds[1]);
if (read(fds[0], &ok, 1) != 1)
exit(4);
wait(&status);
wait(&status);
exit(ok ? 0 : 5);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"
then :
bash_cv_pgrp_pipe=no
else $as_nop
bash_cv_pgrp_pipe=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $bash_cv_pgrp_pipe" >&5
printf "%s\n" "$bash_cv_pgrp_pipe" >&6; }
if test $bash_cv_pgrp_pipe = yes; then
printf "%s\n" "#define PGRP_PIPE 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for type of signal functions" >&5
printf %s "checking for type of signal functions... " >&6; }
if test ${bash_cv_signal_vintage+y}
@@ -18701,6 +18605,9 @@ printf "%s\n" "#define HAVE_USG_SIGHOLD 1" >>confdefs.h
fi
printf "%s\n" "#define PGRP_PIPE 1" >>confdefs.h
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys_errlist and sys_nerr" >&5
printf %s "checking for sys_errlist and sys_nerr... " >&6; }
if test ${bash_cv_sys_errlist+y}
+6 -3
View File
@@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu
dnl
dnl Process this file with autoconf to produce a configure script.
# Copyright (C) 1987-2023 Free Software Foundation, Inc.
# Copyright (C) 1987-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
@@ -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 <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 5.3, version 5.059])dnl
AC_REVISION([for Bash 5.3, version 5.060])dnl
define(bashvers, 5.3)
define(relstatus, devel)
@@ -1030,9 +1030,12 @@ fi
dnl behavior of system calls and library functions
BASH_FUNC_DUP2_CLOEXEC_CHECK
BASH_SYS_PGRP_SYNC
BASH_SYS_SIGNAL_VINTAGE
dnl https://lists.gnu.org/archive/html/bug-bash/2024-01/msg00047.html
dnl BASH_SYS_PGRP_SYNC
AC_DEFINE(PGRP_PIPE)
dnl checking for the presence of certain library symbols
BASH_SYS_ERRLIST
BASH_SYS_SIGLIST
+3
View File
@@ -212,6 +212,9 @@ extern void clock_t_to_secs (clock_t, time_t *, long *);
extern void print_clock_t (FILE *, clock_t);
#endif
/* Declarations for functions defined in lib/sh/compat.c */
extern int compat_init (void);
/* Declarations for functions defined in lib/sh/dprintf.c */
#if !defined (HAVE_DPRINTF)
extern void dprintf (int, const char *, ...) __attribute__((__format__ (printf, 2, 3)));
+7 -3
View File
@@ -3247,7 +3247,8 @@ wait_for_any_job (int flags, struct procstat *ps)
int i, r;
sigset_t set, oset;
if (jobs_list_frozen)
/* Allow funsubs to run this, but don't remove jobs from the jobs table. */
if (jobs_list_frozen && executing_funsub == 0)
return -1;
/* First see if there are any unnotified dead jobs that we can report on */
@@ -3266,8 +3267,11 @@ return_job:
ps->pid = pid;
ps->status = r;
}
notify_of_job_status (); /* XXX */
delete_job (i, 0);
if (jobs_list_frozen == 0) /* must be running a funsub to get here */
{
notify_of_job_status (); /* XXX */
delete_job (i, 0);
}
#if defined (COPROCESS_SUPPORT)
coproc_reap ();
#endif
+1 -1
View File
@@ -109,7 +109,7 @@ sh_stat (const char *path, struct stat *finfo)
effectively a no-op. */
pbuf = xrealloc (pbuf, sizeof (DEV_FD_PREFIX) + strlen (path + 8));
strcpy (pbuf, DEV_FD_PREFIX);
strcat (pbuf, path + 8);
strcpy (pbuf + sizeof (DEV_FD_PREFIX) - 1, path + 8);
return (stat (pbuf, finfo));
#endif /* !HAVE_DEV_FD */
}
+5 -5
View File
@@ -169,7 +169,7 @@ sh_mktmpname (const char *nameroot, int flags)
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
snprintf (filename, PATH_MAX, "%s/%s.XXXXXX", tdir, lroot);
if (mktemp (filename) == 0)
{
free (filename);
@@ -191,7 +191,7 @@ sh_mktmpname (const char *nameroot, int flags)
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
x;
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
snprintf (filename, PATH_MAX, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32) /* XXX */
filename[tdlen + 1 + tmpnamelen] = '\0';
# ifdef HAVE_LSTAT
@@ -229,7 +229,7 @@ sh_mktmpfd (const char *nameroot, int flags, char **namep)
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
snprintf (filename, PATH_MAX, "%s/%s.XXXXXX", tdir, lroot);
fd = mkstemp (filename);
if ((flags & MT_UNLINK) && tmpunlink (filename) < 0)
{
@@ -263,7 +263,7 @@ sh_mktmpfd (const char *nameroot, int flags, char **namep)
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
x;
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
snprintf (filename, PATH_MAX, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32) /* XXX */
filename[tdlen + 1 + tmpnamelen] = '\0';
fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600);
@@ -329,7 +329,7 @@ sh_mktmpdir (const char *nameroot, int flags)
if (flags & MT_TEMPLATE)
strcpy (filename, nameroot);
else
sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
snprintf (filename, PATH_MAX, "%s/%s.XXXXXX", tdir, lroot);
dirname = mkdtemp (filename);
if (dirname == 0)
{
+15 -11
View File
@@ -6995,21 +6995,11 @@ 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)
{
set_exit_status (EXECUTION_FAILURE);
last_read_token = current_token = '\n'; /* XXX */
/* This will eventually call reset_parser */
if (interactive_shell == 0 && posixly_correct)
jump_to_top_level (FORCE_EOF);
else
@@ -7020,6 +7010,20 @@ parse_compound_assignment (size_t *retlenp)
}
}
/* 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;
/* Don't bother with restoring the pushed string list from ps if we're
just going to overwrite it. */
ps.pushed_strings = NULL;
}
restore_parser_state (&ps);
if (restore_pushed_strings)
pushed_string_list = ss;
if (wl)
{
rl = REVERSE_LIST (wl, WORD_LIST *);
+2
View File
@@ -624,6 +624,8 @@ main (int argc, char **argv, char **env)
gnu_error_format = 1;
}
compat_init ();
top_level_arg_index = arg_index;
old_errexit_flag = exit_immediately_on_error;
+1 -1
View File
@@ -6801,7 +6801,7 @@ uw_anonclose (void *fdesc)
static void
uw_unbind_variable (void *name)
{
unbind_variable (name);
unbind_variable_noref (name);
}
static void
+1
View File
@@ -1,3 +1,4 @@
bash: -c: line 1: unexpected EOF while looking for matching `)'
AAA
bash5: line 1: `invalid-name': not a valid identifier
in
+3
View File
@@ -7,6 +7,9 @@ case x in x) if ((1)); then :; fi esac
case x in x) if ((true ) ); then :; fi ;; esac
case x in x) if ((true ) ); then :; fi esac
# problem with bash-5.2
${THIS_SH} -c '((X=([))]' bash
# this has to be in a separate file to get desired EOF behavior
${THIS_SH} ./parser1.sub