and though bugs are the bane of my existence, rest assured the wretched thing will get the best of care here

...
 
Commits (2)
......@@ -9260,3 +9260,45 @@ examples/loadables/stat.c
examples/loadables/Makefile.in
- stat: now built and installed by default
12/31
-----
command.h
- SUBSHELL_IGNTRAP: new flag value
jobs.c
- make_child: set SUBSHELL_IGNTRAP in subshell_environment in the
child process, meaning that we should not execute trap handlers for
trapped signals
execute_cmd.c
- execute_in_subshell, execute_simple_command, execute_disk_command:
make sure to unset SUBSHELL_IGNTRAP after a child process restores
the original signal dispositions
- execute_simple_command: make sure to set SUBSHELL_IGNTRAP after
make_child returns and we're setting subshell_environment directly
subst.c
- command_substitute,process_substitute: unset SUBSHELL_IGNTRAP after
the child process has reset the trapped signal dispositions
trap.c
- trap_handler: if we get a signal for which we have set a trap, but
SUBSHELL_IGNTRAP is set in subshell_environmnent, make sure we
restore the original signal disposition and resend the signal to
ourselves. Fixes issue reported by Nikolay Borisov <nborisov@suse.com>
(or at least makes the race window much smaller)
sig.c
- initialize_terminating_signal: set the original signal handler from
the return value from sigaction; a minor optimization that saves a
system call or two
1/5/2021
--------
builtins/declare.def
- declare_internal: make some option combinations that don't make
sense errors (e.g., -f and -a/-A/-i/-n)
- declare_internal: if we build a new variable name by expanding the
value of a nameref variable, make sure to chop the `+' in a `+='
off before going on
......@@ -1214,6 +1214,7 @@ tests/nameref18.sub f
tests/nameref19.sub f
tests/nameref20.sub f
tests/nameref21.sub f
tests/nameref22.sub f
tests/nameref.right f
tests/new-exp.tests f
tests/new-exp1.sub f
......
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
Copyright (C) 1987-2020 Free Software Foundation, Inc.
Copyright (C) 1987-2021 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
......@@ -306,6 +306,24 @@ declare_internal (list, local_var)
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
}
/* Some option combinations that don't make any sense */
if ((flags_on & att_function) && (flags_on & (att_array|att_assoc|att_integer|att_nameref)))
{
char *optchar;
if (flags_on & att_nameref)
optchar = "-n";
else if (flags_on & att_integer)
optchar = "-i";
else if (flags_on & att_assoc)
optchar = "-A";
else if (flags_on & att_array)
optchar = "-a";
sh_invalidopt (optchar);
return (EXECUTION_FAILURE);
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
......@@ -698,8 +716,8 @@ restart_new_var_name:
assign_error++;
NEXT_VARIABLE ();
}
name[offset] = '\0';
value = name + namelen;
name[(aflags & ASS_APPEND) ? offset - 1 : offset] = '\0';
value = name + namelen; /* XXX name + offset + 1? */
}
free (oldname);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -124,6 +124,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
#define SUBSHELL_IGNTRAP 0x100 /* subshell should reset trapped signals from trap_handler */
/* A structure which represents a word. */
typedef struct word_desc {
......
......@@ -1547,6 +1547,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
clear_pending_traps ();
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
/* Note that signal handlers have been reset, so we should no longer
reset the handler and resend trapped signals to ourselves. */
subshell_environment &= ~SUBSHELL_IGNTRAP;
/* We are in a subshell, so forget that we are running a trap handler or
that the signal handler has changed (we haven't changed it!) */
......@@ -4332,7 +4335,8 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
already_forked = 1;
cmdflags |= CMD_NO_FORK;
subshell_environment = SUBSHELL_FORK; /* XXX */
/* We redo some of what make_child() does with SUBSHELL_IGNTRAP */
subshell_environment = SUBSHELL_FORK|SUBSHELL_IGNTRAP; /* XXX */
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
subshell_environment |= SUBSHELL_PIPE;
if (async)
......@@ -4586,6 +4590,7 @@ run_builtin:
trap strings if we run trap to change a signal disposition. */
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
subshell_environment &= ~SUBSHELL_IGNTRAP;
if (async)
{
......@@ -5526,6 +5531,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
reset_terminating_signals (); /* XXX */
/* Cancel traps, in trap.c. */
restore_original_signals ();
subshell_environment &= ~SUBSHELL_IGNTRAP;
#if defined (JOB_CONTROL)
FREE (p);
......
......@@ -2220,6 +2220,8 @@ make_child (command, flags)
signals to the default state for a new process. */
pid_t mypid;
subshell_environment |= SUBSHELL_IGNTRAP;
/* If this ends up being changed to modify or use `command' in the
child process, go back and change callers who free `command' in
the child process when this returns. */
......
......@@ -575,6 +575,8 @@ make_child (command, flags)
last_asynchronous_pid = getpid ();
#endif
subshell_environment |= SUBSHELL_IGNTRAP;
default_tty_job_signals ();
}
else
......
No preview for this file type
This diff is collapsed.
No preview for this file type
This diff is collapsed.
......@@ -55,7 +55,8 @@
# include "bashhist.h"
#endif
extern void initialize_siglist ();
extern void initialize_siglist PARAMS((void));
extern void set_original_signal PARAMS((int, SigHandler *));
#if !defined (JOB_CONTROL)
extern void initialize_job_signals PARAMS((void));
......@@ -255,6 +256,13 @@ initialize_terminating_signals ()
sigaction (XSIG (i), &act, &oact);
XHANDLER(i) = oact.sa_handler;
XSAFLAGS(i) = oact.sa_flags;
#if 0
set_original_signal (XSIG(i), XHANDLER(i)); /* optimization */
#else
set_original_signal (XSIG(i), act.sa_handler); /* optimization */
#endif
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
/* XXX - should we do this for interactive shells, too? */
......
......@@ -5951,6 +5951,7 @@ process_substitute (string, open_for_read_in_child)
free_pushed_string_input ();
/* Cancel traps, in trap.c. */
restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
subshell_environment &= ~SUBSHELL_IGNTRAP;
QUIT; /* catch any interrupts we got post-fork */
setup_async_signals ();
#if 0
......@@ -6382,6 +6383,7 @@ command_substitute (string, quoted, flags)
}
QUIT; /* catch any interrupts we got post-fork */
subshell_environment |= SUBSHELL_RESETTRAP;
subshell_environment &= ~SUBSHELL_IGNTRAP;
}
#if defined (JOB_CONTROL)
......
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
......
......@@ -11,93 +11,95 @@ declare -fr func
unset: usage: unset [-f] [-v] [-n] [name ...]
./errors.tests: line 55: unset: func: cannot unset: readonly function
./errors.tests: line 58: declare: func: readonly function
./errors.tests: line 62: unset: XPATH: cannot unset: readonly variable
./errors.tests: line 68: unset: cannot simultaneously unset a function and a variable
./errors.tests: line 71: declare: -z: invalid option
./errors.tests: line 62: declare: -a: invalid option
./errors.tests: line 63: declare: -i: invalid option
./errors.tests: line 67: unset: XPATH: cannot unset: readonly variable
./errors.tests: line 73: unset: cannot simultaneously unset a function and a variable
./errors.tests: line 76: declare: -z: invalid option
declare: usage: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
./errors.tests: line 73: declare: `-z': not a valid identifier
./errors.tests: line 74: declare: `/bin/sh': not a valid identifier
./errors.tests: line 78: declare: cannot use `-f' to make functions
./errors.tests: line 81: exec: -i: invalid option
./errors.tests: line 78: declare: `-z': not a valid identifier
./errors.tests: line 79: declare: `/bin/sh': not a valid identifier
./errors.tests: line 83: declare: cannot use `-f' to make functions
./errors.tests: line 86: exec: -i: invalid option
exec: usage: exec [-cl] [-a name] [command [argument ...]] [redirection ...]
./errors.tests: line 85: export: XPATH: not a function
./errors.tests: line 88: break: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 89: continue: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 92: shift: label: numeric argument required
./errors.tests: line 97: shift: too many arguments
./errors.tests: line 103: let: expression expected
./errors.tests: line 106: local: can only be used in a function
./errors.tests: line 109: logout: not login shell: use `exit'
./errors.tests: line 112: hash: notthere: not found
./errors.tests: line 115: hash: -v: invalid option
./errors.tests: line 90: export: XPATH: not a function
./errors.tests: line 93: break: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 94: continue: only meaningful in a `for', `while', or `until' loop
./errors.tests: line 97: shift: label: numeric argument required
./errors.tests: line 102: shift: too many arguments
./errors.tests: line 108: let: expression expected
./errors.tests: line 111: local: can only be used in a function
./errors.tests: line 114: logout: not login shell: use `exit'
./errors.tests: line 117: hash: notthere: not found
./errors.tests: line 120: hash: -v: invalid option
hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
./errors.tests: line 119: hash: hashing disabled
./errors.tests: line 122: export: `AA[4]': not a valid identifier
./errors.tests: line 123: readonly: `AA[4]': not a valid identifier
./errors.tests: line 126: unset: [-2]: bad array subscript
./errors.tests: line 130: AA: readonly variable
./errors.tests: line 134: AA: readonly variable
./errors.tests: line 142: shift: 5: shift count out of range
./errors.tests: line 143: shift: -2: shift count out of range
./errors.tests: line 146: shopt: no_such_option: invalid shell option name
./errors.tests: line 147: shopt: no_such_option: invalid shell option name
./errors.tests: line 150: umask: 09: octal number out of range
./errors.tests: line 151: umask: `:': invalid symbolic mode character
./errors.tests: line 152: umask: `:': invalid symbolic mode operator
./errors.tests: line 155: umask: -i: invalid option
./errors.tests: line 124: hash: hashing disabled
./errors.tests: line 127: export: `AA[4]': not a valid identifier
./errors.tests: line 128: readonly: `AA[4]': not a valid identifier
./errors.tests: line 131: unset: [-2]: bad array subscript
./errors.tests: line 135: AA: readonly variable
./errors.tests: line 139: AA: readonly variable
./errors.tests: line 147: shift: 5: shift count out of range
./errors.tests: line 148: shift: -2: shift count out of range
./errors.tests: line 151: shopt: no_such_option: invalid shell option name
./errors.tests: line 152: shopt: no_such_option: invalid shell option name
./errors.tests: line 155: umask: 09: octal number out of range
./errors.tests: line 156: umask: `:': invalid symbolic mode character
./errors.tests: line 157: umask: `:': invalid symbolic mode operator
./errors.tests: line 160: umask: -i: invalid option
umask: usage: umask [-p] [-S] [mode]
./errors.tests: line 159: umask: `u': invalid symbolic mode character
./errors.tests: line 168: VAR: readonly variable
./errors.tests: line 171: declare: VAR: readonly variable
./errors.tests: line 172: declare: VAR: readonly variable
./errors.tests: line 174: declare: unset: not found
./errors.tests: line 177: VAR: readonly variable
./errors.tests: command substitution: line 181: syntax error near unexpected token `)'
./errors.tests: command substitution: line 181: ` for z in 1 2 3; do )'
./errors.tests: command substitution: line 182: syntax error near unexpected token `done'
./errors.tests: command substitution: line 182: ` for z in 1 2 3; done )'
./errors.tests: line 184: cd: HOME not set
./errors.tests: line 185: cd: /tmp/xyz.bash: No such file or directory
./errors.tests: line 187: cd: OLDPWD not set
./errors.tests: line 188: cd: /bin/sh: Not a directory
./errors.tests: line 190: cd: /tmp/cd-notthere: No such file or directory
./errors.tests: line 193: .: filename argument required
./errors.tests: line 164: umask: `u': invalid symbolic mode character
./errors.tests: line 173: VAR: readonly variable
./errors.tests: line 176: declare: VAR: readonly variable
./errors.tests: line 177: declare: VAR: readonly variable
./errors.tests: line 179: declare: unset: not found
./errors.tests: line 182: VAR: readonly variable
./errors.tests: command substitution: line 186: syntax error near unexpected token `)'
./errors.tests: command substitution: line 186: ` for z in 1 2 3; do )'
./errors.tests: command substitution: line 187: syntax error near unexpected token `done'
./errors.tests: command substitution: line 187: ` for z in 1 2 3; done )'
./errors.tests: line 189: cd: HOME not set
./errors.tests: line 190: cd: /tmp/xyz.bash: No such file or directory
./errors.tests: line 192: cd: OLDPWD not set
./errors.tests: line 193: cd: /bin/sh: Not a directory
./errors.tests: line 195: cd: /tmp/cd-notthere: No such file or directory
./errors.tests: line 198: .: filename argument required
.: usage: . filename [arguments]
./errors.tests: line 194: source: filename argument required
./errors.tests: line 199: source: filename argument required
source: usage: source filename [arguments]
./errors.tests: line 197: .: -i: invalid option
./errors.tests: line 202: .: -i: invalid option
.: usage: . filename [arguments]
./errors.tests: line 200: set: -q: invalid option
./errors.tests: line 205: set: -q: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
./errors.tests: line 203: enable: sh: not a shell builtin
./errors.tests: line 203: enable: bash: not a shell builtin
./errors.tests: line 206: shopt: cannot set and unset shell options simultaneously
./errors.tests: line 209: read: var: invalid timeout specification
./errors.tests: line 212: read: `/bin/sh': not a valid identifier
./errors.tests: line 215: VAR: readonly variable
./errors.tests: line 218: readonly: -x: invalid option
./errors.tests: line 208: enable: sh: not a shell builtin
./errors.tests: line 208: enable: bash: not a shell builtin
./errors.tests: line 211: shopt: cannot set and unset shell options simultaneously
./errors.tests: line 214: read: var: invalid timeout specification
./errors.tests: line 217: read: `/bin/sh': not a valid identifier
./errors.tests: line 220: VAR: readonly variable
./errors.tests: line 223: readonly: -x: invalid option
readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p
./errors.tests: line 221: eval: -i: invalid option
./errors.tests: line 226: eval: -i: invalid option
eval: usage: eval [arg ...]
./errors.tests: line 222: command: -i: invalid option
./errors.tests: line 227: command: -i: invalid option
command: usage: command [-pVv] command [arg ...]
./errors.tests: line 225: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 226: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 229: trap: NOSIG: invalid signal specification
./errors.tests: line 232: trap: -s: invalid option
./errors.tests: line 230: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 231: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
./errors.tests: line 234: trap: NOSIG: invalid signal specification
./errors.tests: line 237: trap: -s: invalid option
trap: usage: trap [-lp] [[arg] signal_spec ...]
./errors.tests: line 238: return: can only `return' from a function or sourced script
./errors.tests: line 242: break: 0: loop count out of range
./errors.tests: line 246: continue: 0: loop count out of range
./errors.tests: line 251: builtin: bash: not a shell builtin
./errors.tests: line 255: bg: no job control
./errors.tests: line 256: fg: no job control
./errors.tests: line 259: kill: -s: option requires an argument
./errors.tests: line 261: kill: S: invalid signal specification
./errors.tests: line 263: kill: `': not a pid or valid job spec
./errors.tests: line 243: return: can only `return' from a function or sourced script
./errors.tests: line 247: break: 0: loop count out of range
./errors.tests: line 251: continue: 0: loop count out of range
./errors.tests: line 256: builtin: bash: not a shell builtin
./errors.tests: line 260: bg: no job control
./errors.tests: line 261: fg: no job control
./errors.tests: line 264: kill: -s: option requires an argument
./errors.tests: line 266: kill: S: invalid signal specification
./errors.tests: line 268: kill: `': not a pid or valid job spec
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
./errors.tests: line 268: set: trackall: invalid option name
./errors.tests: line 272: xx: readonly variable
./errors.tests: line 273: set: trackall: invalid option name
./errors.tests: line 277: xx: readonly variable
1
./errors1.sub: line 14: .: -i: invalid option
.: usage: . filename [arguments]
......@@ -197,4 +199,4 @@ ok 6
bash: line 1: return: can only `return' from a function or sourced script
after return
bash: line 1: return: can only `return' from a function or sourced script
./errors.tests: line 299: `!!': not a valid identifier
./errors.tests: line 304: `!!': not a valid identifier
......@@ -57,6 +57,11 @@ unset -f func
declare -fr func
declare -f +r func
# cannot use declare -f in combination with other attributes
a() { echo a; }
declare -f -a a
declare -f -i b c
XPATH=$PATH
declare -r XPATH
unset -v XPATH
......
......@@ -348,6 +348,10 @@ declare -a v=([1]="1")
declare -a v=([0]="0" [1]="1")
declare -n n="v[1]"
declare -a v=([0]="0")
./nameref15.sub: line 120: warning: xref: removing nameref attribute
declare -a xref=([1]="one")
./nameref15.sub: line 126: warning: xref: removing nameref attribute
declare -a xref=([1]="one")
declare -n r1="y"
declare -n r2="x"
./nameref16.sub: line 25: typeset: x: not found
......@@ -440,6 +444,8 @@ declare -n foo="bar"
declare -- bar
declare -- foo="bar"
declare -- bar
8
declare -n ivar="foo"
declare -a v=([0]="Y")
r: <Y>
v: <Y>
......@@ -483,3 +489,24 @@ declare -n ref="var"
declare -ai var=([1]="0")
declare -n ref="var"
declare -- var="1"
a string with spaces
many spaces
declare -n foo="bar[0]"
declare -a bar=([0]=" still more spaces")
declare -n foo="bar[0]"
declare -a bar=([0]="spaces still more spaces")
./nameref22.sub: line 50: declare: array: reference variable cannot be an array
./nameref22.sub: line 53: declare: array[128]: reference variable cannot be an array
declare -a array=([0]="one" [1]="two" [2]="three")
declare -- array="(one two three)"
declare -a array=([0]="one" [1]="two" [2]="three")
./nameref22.sub: line 69: declare: `(one two three)': invalid variable name for name reference
./nameref22.sub: line 70: declare: array: reference variable cannot be an array
declare -a array=([0]="zero")
./nameref22.sub: line 74: declare: array: reference variable cannot be an array
declare -a array=([0]="one" [1]="two" [2]="three")
./nameref22.sub: line 79: declare: array: reference variable cannot be an array
declare -a array
declare -ai array=([0]="one")
declare -a array=([0]="zero")
declare -a array=([0]="one" [1]="two" [2]="three")
......@@ -115,3 +115,13 @@ v=(0 1)
declare -n n=v[1]
unset n
declare -p n v
declare -n xref
declare -a xref[1]=one
declare -p xref
unset xref
declare -n xref
xref=array
declare -a xref[1]=one
declare -p xref
......@@ -62,3 +62,12 @@ declare bar
declare -p foo bar
declare +n foo
declare -p foo bar
# but when we add the nameref attribute, we remove other attributes
declare -i ivar
ivar=4+4
echo $ivar
declare -n ivar=foo
declare -p ivar
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
declare -n foo=bar
declare foo='a string with spaces'
echo $foo
unset foo
declare foo+='many spaces'
echo $foo
unset foo # unsets bar
unset -n foo
declare -a bar
declare -n foo='bar[0]'
declare foo+=' still more spaces'
declare -p foo bar
unset -n foo
unset bar
declare -a bar
declare -n foo='bar[0]'
declare foo=spaces
declare foo+=' still more spaces'
declare -p foo bar
unset -n foo
unset bar
ray=ray
declare -a array
array[0]=zero
declare -n array
unset array
declare -n array[128]
unset array
declare -a array='(one two three)'
declare -p array
unset array
declare array='(one two three)'
declare -p array
unset array
declare -a ar$ray='(one two three)'
declare -p ar$ray
unset array
declare -a array=(zero)
declare -n array='(one two three)'
declare -n array=three
declare -p array
unset array
declare -n array=(one two three)
declare -p array
unset array
declare -a array
declare -n array=one
declare -p array
unset array
array=one
declare -i array[64];
declare -p array
unset array
declare -a array=zero
declare -p array
unset array
declare -a array
declare array='(one two three)'
declare -p array
unset array
......@@ -481,6 +481,32 @@ trap_handler (sig)
SIGRETURN (0);
}
/* This means we're in a subshell, but have not yet reset the handler for
trapped signals. We're not supposed to execute the trap in this situation;
we should restore the original signal and resend the signal to ourselves
to preserve the Posix "signal traps that are not being ignored shall be
set to the default action" semantics. */
if ((subshell_environment & SUBSHELL_IGNTRAP) && trap_list[sig] != (char *)IGNORE_SIG)
{
sigset_t mask;
/* Paranoia */
if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
original_signals[sig] = SIG_DFL;
restore_signal (sig);
/* Make sure we let the signal we just caught through */
sigemptyset (&mask);
sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
sigdelset (&mask, sig);
sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
kill (getpid (), sig);
SIGRETURN (0);
}
if ((sig >= NSIG) ||
(trap_list[sig] == (char *)DEFAULT_SIG) ||
(trap_list[sig] == (char *)IGNORE_SIG))
......