commit bash-20161122 snapshot

This commit is contained in:
Chet Ramey
2016-12-01 16:58:13 -05:00
parent 31a8d95a37
commit 1975c9b5fa
15 changed files with 212 additions and 44 deletions
+104
View File
@@ -12458,3 +12458,107 @@ builtins/shopt.def
builtins/common.c
- display_signal_list: make `kill -l 0' print `EXIT', modifying change
from 9/17
11/21
-----
subst.c
- expand_word_internal: when the shell encounters a backslash as the
last character of the string, don't try to add a '\'0' to the end
of the string if the string is quoted, just add a <CTLESC><\> and
skip to the end of string processing. Fixes oob-read error
reported by Jerzy Kramarz <op7ica@gmail.com>
test.c
- two_arguments: check argv[pos][1] before checking argv[pos][2] when
looking for a unary argument. Fixes oob-read error on single `-'
in unary operator position reported by Jerzy Kramarz
<op7ica@gmail.com>
- ANDOR: check s[1] before checking s[2] in case s[1] == end of string.
Fixes oob-read error reported by Jerzy Kramarz <op7ica@gmail.com>
subst.c
- command_substitute: now takes additional flags argument, changed one
caller (param_expand) to pass through PF_ASSIGNRHS flag; other callers
pass 0
- command_substitute: pass through flags argument to read_comsub
- read_comsub: now takes additional new flags argument to indicate
whether or not the word is in a context where word splitting will
eventually be performed
- read_comsub: if we are running in a context where word splitting
will not take place (PF_ASSIGNRHS), we read a CTLESC, and CTLESC is
in $IFS, add a CTLESC to make sure it gets through a round of
dequoting
11/23
-----
parse.y
- xparse_dolparen: since reset_parser frees the pushed string list,
and this is supposed to be a separate parsing context, we need to
save and restore pushed_string_list around the call to parse_string
and reset_parser. Fixes bug reported by Dan Douglas
<ormaaj@gmail.com>
bashhist.h
- HISTEXPAND_DEFAULT: default value of history_expansion, moved here
from flags.c
flags.[ch]
- histexp_flag: new variable, this is what set -H/set -o histexpand
sets; history_expansion set to value of this variable; defaults to 0
- history_expansion: now set to HISTEXPAND_DEFAULT
bashhist.c
- bash_history_reinit: if interact == 0, set history_expansion to the
value of histexp_flag, to allow -H option to enable history
expansion
- bash_history_reinit: if interact == 0, make sure
history_expansion_inhibited is set opposite of histexp_flag, so
enabling history expansion with -H invocation option turns off
inhibited expansion. If interactive shell, we turn it off so
history_expansion controls whether or not history expansion takes
place. In practice, this function is always called with interact == 0,
and -c command still doesn't perform history expansion
shell.c
- init_interactive: make sure histexp_flag and history_expansion are
identical in an interactive shell; allows both -H/+H option and
default compilation options (HISTEXPAND_DEFAULT) to work
11/24
-----
subst.c
- get_word_from_string: take advantage of the fact that SEPARATORS is
always a (possibly local) copy of IFS, so build a local charmap of
separators and use it instead of the (cached and possibly stale)
ifs_cmap map and isifs macro. Fixes bug with -N stripping leading
whitespace reported by Clark Wang <clarkw@vmware.com>
11/25
-----
builtins/read.def
- read_builtin: make `i' volatile, since auto variables are technically
undefined after a longjmp, and a timeout on SIGALRM causes one.
Fix suggested by Dmitry Goncharov <dgoncharov@users.sf.net>
11/27
-----
parse.y
- shell_getc: if we are reading input from a string, and we get the
ending '\0', and we are not expanding an alias, return EOF right
away. It might be an eval'ed string that has a syntax error.
Fixes bug reported by Dan Douglas <ormaaj@gmail.com>
11/28
-----
subst.c
- expand_word_internal: if we're expanding a quoted string containing
a tilde as the first character of a word, only expand the tilde if
we're expanding an array subscript (Q_ARRAYSUB), not if we're
expanding any arithmetic expression (Q_ARITH). This fixes a
backwards compatibility issue with expressions like ~0 reported by
Bize Ma <binaryzebra@gmail.com>
subst.c
- parameter_brace_expand_indir: if the variable is not special and
the indirect variable is unset (!variable where variable is unset),
report an error. Fixes omission reported by otenba@protonmail.com
+2 -2
View File
@@ -272,8 +272,8 @@ bash_history_reinit (interact)
int interact;
{
#if defined (BANG_HISTORY)
history_expansion = interact != 0;
history_expansion_inhibited = 1; /* XXX */
history_expansion = (interact == 0) ? histexp_flag : HISTEXPAND_DEFAULT;
history_expansion_inhibited = (interact == 0) ? 1 - histexp_flag : 0; /* changed in bash_history_enable() */
history_inhibit_expansion_function = bash_history_inhibit_expansion;
#endif
remember_on_history = enable_history_list;
+6
View File
@@ -30,6 +30,12 @@
#define HC_IGNBOTH (HC_IGNSPACE|HC_IGNDUPS)
#if defined (STRICT_POSIX)
# define HISTEXPAND_DEFAULT 0
#else
# define HISTEXPAND_DEFAULT 1
#endif
extern int remember_on_history;
extern int enable_history_list; /* value for `set -o history' */
extern int literal_history; /* controlled by `shopt lithist' */
+2 -1
View File
@@ -178,7 +178,8 @@ read_builtin (list)
WORD_LIST *list;
{
register char *varname;
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
int size, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
volatile int i;
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd, lastsig, t_errno;
int mb_cur_max;
+2 -1
View File
@@ -2794,7 +2794,8 @@ Any incorrectly formed brace expansion is left unchanged.
A \fB{\fP or \fB,\fP may be quoted with a backslash to prevent its
being considered part of a brace expression.
To avoid conflicts with parameter expansion, the string \fB${\fP
is not considered eligible for brace expansion.
is not considered eligible for brace expansion, and inhibits brace
expansion until the closing \fB}\fP.
.PP
This construct is typically used as shorthand when the common
prefix of the strings to be generated is longer than in the
+2 -1
View File
@@ -1766,7 +1766,8 @@ in the result. It is strictly textual. Bash
does not apply any syntactic interpretation to the context of the
expansion or the text between the braces.
To avoid conflicts with parameter expansion, the string @samp{$@{}
is not considered eligible for brace expansion.
is not considered eligible for brace expansion,
and inhibits brace expansion until the closing @samp{@}}..
A correctly-formed brace expansion must contain unquoted opening
and closing braces, and at least one unquoted comma or a valid
+3
View File
@@ -4381,7 +4381,10 @@ run_builtin:
}
result = builtin_status (result);
if (builtin_is_special)
{
itrace("special builtin failed with flags = %d", simple_command->flags);
special_builtin_failed = 1;
}
}
/* In POSIX mode, if there are assignment statements preceding
a special builtin, they persist after the builtin
+4 -6
View File
@@ -130,11 +130,8 @@ int hashing_enabled = 1;
#if defined (BANG_HISTORY)
/* Non-zero means that we are doing history expansion. The default.
This means !22 gets the 22nd line of history. */
# if defined (STRICT_POSIX)
int history_expansion = 0;
# else
int history_expansion = 1;
# endif
int history_expansion = HISTEXPAND_DEFAULT;
int histexp_flag = 0;
#endif /* BANG_HISTORY */
/* Non-zero means that we allow comments to appear in interactive commands. */
@@ -211,7 +208,7 @@ const struct flags_alist shell_flags[] = {
{ 'C', &noclobber },
{ 'E', &error_trace_mode },
#if defined (BANG_HISTORY)
{ 'H', &history_expansion },
{ 'H', &histexp_flag },
#endif /* BANG_HISTORY */
{ 'I', &no_invisible_vars },
{ 'P', &no_symbolic_links },
@@ -265,6 +262,7 @@ change_flag (flag, on_or_off)
{
#if defined (BANG_HISTORY)
case 'H':
history_expansion = histexp_flag;
if (on_or_off == FLAG_ON)
bash_initialize_history ();
break;
+1
View File
@@ -60,6 +60,7 @@ extern int brace_expansion;
#if defined (BANG_HISTORY)
extern int history_expansion;
extern int histexp_flag;
#endif /* BANG_HISTORY */
#if defined (RESTRICTED_SHELL)
+2
View File
@@ -46,6 +46,8 @@
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
#define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
#define FNM_FIRSTCHAR (1 << 6) /* Match only the first character */
/* Value returned by `strmatch' if STRING does not match PATTERN. */
#undef FNM_NOMATCH
+23 -1
View File
@@ -2311,6 +2311,14 @@ shell_getc (remove_quoted_newline)
#if 0
internal_warning ("shell_getc: ignored null byte in input");
#endif
if (bash_input.type == st_string)
{
if (i == 0)
shell_input_line_terminator = EOF;
shell_input_line[i] = '\0';
c = EOF;
break;
}
continue;
}
@@ -3131,6 +3139,15 @@ read_token (command)
return (yacc_EOF);
}
/* If we hit the end of the string and we're not expanding an alias (e.g.,
we are eval'ing a string that is an incomplete command), return EOF */
if (character == '\0' && bash_input.type == st_string && expanding_alias() == 0)
{
itrace("shell_getc: bash_input.location.string = `%s'", bash_input.location.string);
EOF_Reached = 1;
return (yacc_EOF);
}
if MBTEST(character == '#' && (!interactive || interactive_comments))
{
/* A comment. Discard until EOL or EOF, and then return a newline. */
@@ -4226,6 +4243,7 @@ xparse_dolparen (base, string, indp, flags)
sh_input_line_state_t ls;
int orig_ind, nc, sflags, orig_eof_token;
char *ret, *s, *ep, *ostring;
STRING_SAVER *saved_pushed_strings;
/*yydebug = 1;*/
orig_ind = *indp;
@@ -4238,6 +4256,8 @@ xparse_dolparen (base, string, indp, flags)
save_parser_state (&ps);
save_input_line_state (&ls);
orig_eof_token = shell_eof_token;
saved_pushed_strings = pushed_string_list; /* separate parsing context */
pushed_string_list = (STRING_SAVER *)NULL;
/*(*/
parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
@@ -4251,6 +4271,8 @@ xparse_dolparen (base, string, indp, flags)
/* reset_parser clears shell_input_line and associated variables */
restore_input_line_state (&ls);
pushed_string_list = saved_pushed_strings;
token_to_read = 0;
/* If parse_string returns < 0, we need to jump to top level with the
@@ -4260,7 +4282,7 @@ xparse_dolparen (base, string, indp, flags)
/* Need to find how many characters parse_and_execute consumed, update
*indp, if flags != 0, copy the portion of the string parsed into RET
and return it. If flags & 1 (EX_NOALLOC) we can return NULL. */
and return it. If flags & 1 (SX_NOALLOC) we can return NULL. */
/*(*/
if (ep[-1] != ')')
+1
View File
@@ -1722,6 +1722,7 @@ init_interactive ()
interactive = 1;
#if defined (HISTORY)
remember_on_history = enable_history_list = 1; /* XXX */
histexp_flag = history_expansion; /* XXX */
#endif
}
+57 -29
View File
@@ -309,7 +309,7 @@ static char *parameter_brace_transform __P((char *, char *, int, char *, int, in
static char *process_substitute __P((char *, int));
static char *read_comsub __P((int, int, int *));
static char *read_comsub __P((int, int, int, int *));
#ifdef ARRAY_VARS
static arrayind_t array_length_reference __P((char *));
@@ -2851,11 +2851,15 @@ list_string (string, separators, quoted)
/* Parse a single word from STRING, using SEPARATORS to separate fields.
ENDPTR is set to the first character after the word. This is used by
the `read' builtin. This is never called with SEPARATORS != $IFS;
it should be simplified.
the `read' builtin.
This is never called with SEPARATORS != $IFS, and takes advantage of that.
XXX - this function is very similar to list_string; they should be
combined - XXX */
#define islocalsep(c) (local_cmap[(unsigned char)(c)] != 0)
char *
get_word_from_string (stringp, separators, endptr)
char **stringp, *separators, **endptr;
@@ -2863,6 +2867,7 @@ get_word_from_string (stringp, separators, endptr)
register char *s;
char *current_word;
int sindex, sh_style_split, whitesep, xflags;
unsigned char local_cmap[UCHAR_MAX+1]; /* really only need single-byte chars here */
size_t slen;
if (!stringp || !*stringp || !**stringp)
@@ -2872,20 +2877,23 @@ get_word_from_string (stringp, separators, endptr)
separators[1] == '\t' &&
separators[2] == '\n' &&
separators[3] == '\0';
for (xflags = 0, s = ifs_value; s && *s; s++)
memset (local_cmap, '\0', sizeof (local_cmap));
for (xflags = 0, s = separators; s && *s; s++)
{
if (*s == CTLESC) xflags |= SX_NOCTLESC;
if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
local_cmap[(unsigned char)*s] = 1; /* local charmap of separators */
}
s = *stringp;
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. */
if (sh_style_split || !separators || !*separators)
long as those characters appear in SEPARATORS. This happens if
SEPARATORS == $' \t\n' or if IFS is unset. */
if (sh_style_split || separators == 0)
{
for (; *s && spctabnl (*s) && isifs (*s); s++);
for (; *s && spctabnl (*s) && islocalsep (*s); s++);
/* If the string is nothing but whitespace, update it and return. */
if (!*s)
@@ -2925,19 +2933,19 @@ get_word_from_string (stringp, separators, endptr)
/* Now skip sequences of space, tab, or newline characters if they are
in the list of separators. */
while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
while (s[sindex] && spctabnl (s[sindex]) && islocalsep (s[sindex]))
sindex++;
/* If the first separator was IFS whitespace and the current character is
a non-whitespace IFS character, it should be part of the current field
delimiter, not a separate delimiter that would result in an empty field.
Look at POSIX.2, 3.6.5, (3)(b). */
if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
if (s[sindex] && whitesep && islocalsep (s[sindex]) && !spctabnl (s[sindex]))
{
sindex++;
/* An IFS character that is not IFS white space, along with any adjacent
IFS white space, shall delimit a field. */
while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
while (s[sindex] && spctabnl (s[sindex]) && islocalsep(s[sindex]))
sindex++;
}
@@ -3716,10 +3724,12 @@ expand_string_assignment (string, quoted)
expand_no_split_dollar_star = 1;
#if 0
/* Other shells (ksh93) do it this way, affects how $@ is expanded in
constructs like bar=${@#0} (preserves the spaces resulting from the
expansion of $@ in a context where you don't do word splitting) */
td.flags = W_ASSIGNRHS|W_NOSPLIT2;
/* Other shells (ksh93) do it this way, which affects how $@ is expanded
in constructs like bar=${@#0} (preserves the spaces resulting from the
expansion of $@ in a context where you don't do word splitting); Posix
interp 888 makes the expansion of $@ in contexts where word splitting
is not performed unspecified. */
td.flags = W_ASSIGNRHS|W_NOSPLIT2; /* Posix interp 888 */
#else
td.flags = W_ASSIGNRHS;
#endif
@@ -4542,7 +4552,7 @@ match_upattern (string, pat, mtype, sp, ep)
p = npat = (char *)xmalloc (len + 3);
p1 = pat;
if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob))
if ((mtype != MATCH_BEG) && (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob)))
*p++ = '*';
while (*p1)
*p++ = *p1++;
@@ -4553,7 +4563,7 @@ match_upattern (string, pat, mtype, sp, ep)
/* If the pattern ends with a `*' we leave it alone if it's preceded by
an even number of backslashes, but if it's escaped by a backslash
we need to add another `*'. */
if (p1[-1] == '*' && (unescaped_backslash = p1[-2] == '\\'))
if ((mtype != MATCH_END) && (p1[-1] == '*' && (unescaped_backslash = p1[-2] == '\\')))
{
pp = p1 - 3;
while (pp >= pat && *pp-- == '\\')
@@ -4561,7 +4571,7 @@ match_upattern (string, pat, mtype, sp, ep)
if (unescaped_backslash)
*p++ = '*';
}
else if (p1[-1] != '*')
else if (mtype != MATCH_END && p1[-1] != '*')
*p++ = '*';
#else
if (p1[-1] != '*' || p1[-2] == '\\')
@@ -5999,8 +6009,8 @@ process_substitute (string, open_for_read_in_child)
/***********************************/
static char *
read_comsub (fd, quoted, rflag)
int fd, quoted;
read_comsub (fd, quoted, flags, rflag)
int fd, quoted, flags;
int *rflag;
{
char *istring, buf[128], *bufp, *s;
@@ -6011,13 +6021,8 @@ read_comsub (fd, quoted, rflag)
istring = (char *)NULL;
istring_index = istring_size = bufn = tflag = 0;
#if 0
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
#else
skip_ctlesc = ifs_cmap[CTLESC];
skip_ctlnul = ifs_cmap[CTLNUL];
#endif
nullbyte = 0;
@@ -6054,6 +6059,8 @@ read_comsub (fd, quoted, rflag)
/* This is essentially quote_string inline */
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
istring[istring_index++] = CTLESC;
else if ((flags & PF_ASSIGNRHS) && skip_ctlesc && c == CTLESC)
istring[istring_index++] = CTLESC;
/* Escape CTLESC and CTLNUL in the output to protect those characters
from the rest of the word expansions (word splitting and globbing.)
This is essentially quote_escapes inline. */
@@ -6340,7 +6347,7 @@ command_substitute (string, quoted, flags)
close (fildes[1]);
tflag = 0;
istring = read_comsub (fildes[0], quoted, &tflag);
istring = read_comsub (fildes[0], quoted, flags, &tflag);
close (fildes[0]);
@@ -6745,6 +6752,15 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
}
}
if (var_is_special == 0 && v == 0)
{
report_error (_("%s: invalid indirect expansion"), name);
w = alloc_word_desc ();
w->word = &expand_param_error;
w->flags = 0;
return (w);
}
t = parameter_brace_find_indir (name, var_is_special, quoted, 0);
chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
@@ -6753,7 +6769,7 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
if (valid_brace_expansion_word (t, SPECIAL_VAR (t, 0)) == 0)
{
report_error (_("%s: bad substitution"), t);
report_error (_("%s: invalid variable name"), t);
free (t);
w = alloc_word_desc ();
w->word = &expand_param_error;
@@ -9202,7 +9218,7 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
mb_cur_max = MB_CUR_MAX;
/* Don't need the string length for the SADD... and COPY_ macros unless
multibyte characters are possible. */
multibyte characters are possible, but do need it for bounds checking. */
string_size = (mb_cur_max > 1) ? strlen (string) : 1;
if (contains_dollar_at)
@@ -9351,10 +9367,13 @@ add_string:
at the start of a word or after an unquoted : or = in an
assignment statement, we don't do tilde expansion. If we don't want
tilde expansion when expanding words to be passed to the arithmetic
evaluator, remove the check for Q_ARITH. */
evaluator, remove the check for Q_ARITH. Right now, the code
suppresses tilde expansion when expanding in a pure arithmetic
context, but allows it when expanding an array subscript. This is
for backwards compatibility, but I figure nobody's relying on it */
if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
(sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) && ((quoted & Q_ARITH) == 0)))
((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) && ((quoted & Q_ARRAYSUB) == 0)))
{
word->flags &= ~W_ITILDE;
if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
@@ -9515,6 +9534,15 @@ add_string:
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && c == 0)
{
RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
DEFAULT_ARRAY_SIZE);
istring[istring_index++] = CTLESC;
istring[istring_index++] = '\\';
istring[istring_index] = '\0';
break;
}
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
{
SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
+2 -2
View File
@@ -740,7 +740,7 @@ two_arguments ()
{
if (argv[pos][0] == '!' && argv[pos][1] == '\0')
return (argv[pos + 1][0] == '\0');
else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][2] == '\0')
{
if (test_unop (argv[pos]))
return (unary_operator ());
@@ -753,7 +753,7 @@ two_arguments ()
return (0);
}
#define ANDOR(s) (s[0] == '-' && !s[2] && (s[1] == 'a' || s[1] == 'o'))
#define ANDOR(s) (s[0] == '-' && (s[1] == 'a' || s[1] == 'o') && s[2] == 0)
/* This could be augmented to handle `-t' as equivalent to `-t 1', but
POSIX requires that `-t' be given an argument. */
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR