commit bash-20160923 snapshot

This commit is contained in:
Chet Ramey
2016-09-27 10:40:02 -04:00
parent f036615e27
commit 61c476d20d
27 changed files with 420 additions and 347 deletions
+127
View File
@@ -11719,3 +11719,130 @@ print_cmd.c
- print_deferred_heredocs: don't print heredoc headers, since they're
now printed in print_redirection_list
- print_deferred_heredocs: use print_heredoc_bodies
9/20
----
builtins/mapfile.def
- readarray: update usage synopsis to include -d delim. Report and
fix from jhankins@homewood.k12.al.us
test.c
- test_binop: if op[0] == '-', make sure op[1] != 0 before checking
op[2] or op[3]. Fixes out-of-bounds read reported by Franco
Costantini <franco.costantini.20@gmail.com>
parse.y
- cond_term: if yylval.word->word[0] == '-' make sure word[1] != 0
before checking word[2] and calling test_unop. Fixes out-of-bounds
read reported by Franco Costantini <franco.costantini.20@gmail.com>
- make sure to check all instances of the return value of the
simple_command production before trying to hook redirections onto it,
since it can potentially return NULL.
Reported by Franco Costantini <franco.costantini.20@gmail.com>
9/21
----
parse.y
- token_is_assignment: make sure to check that the return value from
assignment() finds the `=' we just added at index I to avoid false
positives from g=g=g=g=g=g=(). Reported by Franco Costantini
<franco.costantini.20@gmail.com>
9/22
----
parse.y
- token_is_assignment: if we're not using the bash malloc (which has
guard bytes after the requested allocation size), use a new
buffer so we can make sure it's big enough to hold the current
token and at least two additional characters. Reported by
Franco Costantini <franco.costantini.20@gmail.com>
9/23
----
execute_command.c
- execute_in_subshell: call without_job_control for both job control
and non-job-control builds to avoid waiting for last_made_pid
inherited from parent shell. Related to fix from 8/4 to
initialize_subshell. Fixes bug reported by Martijn Dekker
<martijn@inlv.org>
builtins/declare.def
- local_builtin: allow `local --help' to work even when not executing
a function. Suggestion from Norm Abramovitz <norm@starkandwayne.com>
9/25
----
builtins/printf.def
- bexpand: if passed a null or empty string, return a newly-allocated
empty string (so the return value can always be freed) instead of
NULL.
- printstr: if passed a null string, treat it as if it were an empty
string so any precision or fieldwidth arguments are handled
correctly. Report from isabella parakiss <izaberina@gmail.com>
subst.c
- skip_matched_pair: make the flags argument of 1 affect whether or
not backslash can quote characters in the string, so it affects
all quoting mechanisms
arrayfunc.c
- unbind_array_element: now takes a third (flags) argument; flags&1
means to not expand an associative array index. This is only called
from a shell builtin context, which means the argument should have
already undergone word expansion, so it should be ok. Will still
be a problem for uses like "unset -v 'var[$ind]'", quoted to avoid
globbing
- valid_array_reference: pass second flags argument to skipsubscript;
still set to 0 by all callers
arrayfunc.h
- unbind_array_element: updated prototype
builtins/set.def
- unset_builtin: add third argument of 1 to unbind_array_element calls
[TEMPORARILY DISABLED]
- unset_builtin: call valid_array_reference with second arg of 1 to
handle unmatched pairs of quotes and [/]
array.c
- array_reference: optimize access locality as well as sequential
access by adding ability to start from last-accessed element and move
backwards or forwards depending on the desired index. Inspired by
report from Tom McCurdy <tom.j.mccurdy@gmail.com> and followup from
Christian Franke <Christian.Franke@t-online.de>
variables.c
- all_array_variables: include associative arrays, not just indexed
arrays. Reported by Grisha Levit <grishalevit@gmail.com>
execute_cmd.c
- execute_disk_command: if we're optimizing out the fork (CMD_NO_FORK),
decrement the shell level so we don't end up incrementing it twice.
We should decrement the shell level for an implicit exec like an
explicit one. Reported by Stephane Chazelas
<stephane.chazelas@gmail.com>
builtins/exec.def
- exec_builtin: don't bother to decrement the shell level if we are
already in a `(command)' subshell. Reported by Stephane Chazelas
<stephane.chazelas@gmail.com>
lib/readline/macro.c
- macro_level: count of macro nesting level, maintained by
_rl_push_executing_macro and _rl_pop_executing macro
- _rl_with_macro_input: if current nesting level exceeds
MAX_MACRO_LEVEL, abort the current command line with _rl_abort_internal
and return to the top level. Reported by Christian Klomp
<christianklomp@gmail.com>
lib/readine/history.c
- add_history: if allocating the history list for the first time,
make sure the max history list size isn't so large that it will
cause allocation errors. Cap it at MAX_HISTORY_INITIAL_SIZE
(8192). Reported by Sean Zha <freeman_cha@hotmail.com>
jobs.c
- wait_for: if a foreground job with job control enabled is killed by a
SIGINT and sourcelevel != 0, act as if we received the SIGINT so the
file sourcing can be terminated. Reported by PePa
<peterkelly@passchier.net>
+18 -2
View File
@@ -67,6 +67,8 @@ static ARRAY_ELEMENT *lastref = 0;
(IS_LASTREF(a) && i >= element_index(lastref)) ? lastref \
: element_forw(a->head)
#define LASTREF(a) IS_LASTREF(a) ? lastref : element_forw(a->head)
#define INVALIDATE_LASTREF(a) \
do { \
if ((a) == lastarray) { \
@@ -711,17 +713,31 @@ ARRAY *a;
arrayind_t i;
{
register ARRAY_ELEMENT *ae, *start;
arrayind_t startind;
int direction;
if (a == 0 || array_empty(a))
return((char *) NULL);
if (i > array_max_index(a))
return((char *)NULL); /* Keep roving pointer into array to optimize sequential access */
start = LASTREF_START(a, i);
for (ae = start; ae != a->head; ae = element_forw(ae))
start = LASTREF(a); /* lastref pointer */
startind = element_index(start);
if (i < startind/2) { /* XXX - guess */
start = element_forw(a->head);
startind = element_index(start);
direction = 1;
} else if (i >= startind) {
direction = 1;
} else {
direction = -1;
}
for (ae = start; ae != a->head; ) {
if (element_index(ae) == i) {
SET_LASTREF(a, ae);
return(element_value(ae));
}
ae = (direction == 1) ? element_forw(ae) : element_back(ae);
}
UNSET_LASTREF(); /* XXX SET_LASTREF(a, start) ? */
return((char *) NULL);
}
+6 -4
View File
@@ -760,9 +760,10 @@ quote_array_assignment_chars (list)
`[' of an array subscript and removes the array element to which SUB
expands from array VAR. A subscript of `*' or `@' unsets the array. */
int
unbind_array_element (var, sub)
unbind_array_element (var, sub, flags)
SHELL_VAR *var;
char *sub;
int flags;
{
int len;
arrayind_t ind;
@@ -790,7 +791,7 @@ unbind_array_element (var, sub)
if (assoc_p (var))
{
akey = expand_assignment_string_to_string (sub, 0); /* [ */
akey = (flags & 1) ? sub : expand_assignment_string_to_string (sub, 0);
if (akey == 0 || *akey == 0)
{
builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
@@ -798,7 +799,8 @@ unbind_array_element (var, sub)
return -1;
}
assoc_remove (assoc_cell (var), akey);
free (akey);
if (akey != sub)
free (akey);
}
else if (array_p (var))
{
@@ -896,7 +898,7 @@ valid_array_reference (name, flags)
if (r == 0)
return 0;
/* Check for a properly-terminated non-blank subscript. */
len = skipsubscript (t, 0, 0);
len = skipsubscript (t, 0, flags);
if (t[len] != ']' || len == 1)
return 0;
if (t[len+1] != '\0')
+1 -1
View File
@@ -52,7 +52,7 @@ extern WORD_LIST *expand_compound_array_assignment __P((SHELL_VAR *, char *, int
extern void assign_compound_array_list __P((SHELL_VAR *, WORD_LIST *, int));
extern SHELL_VAR *assign_array_var_from_string __P((SHELL_VAR *, char *, int));
extern int unbind_array_element __P((SHELL_VAR *, char *));
extern int unbind_array_element __P((SHELL_VAR *, char *, int));
extern int skipsubscript __P((const char *, int, int));
extern void print_array_assignment __P((SHELL_VAR *, int));
+7
View File
@@ -120,6 +120,13 @@ int
local_builtin (list)
register WORD_LIST *list;
{
/* Catch a straight `local --help' before checking function context */
if (list && list->word && STREQ (list->word->word, "--help"))
{
builtin_help ();
return (EX_USAGE);
}
if (variable_context)
return (declare_internal (list, 1));
else
+5 -2
View File
@@ -190,8 +190,11 @@ exec_builtin (list)
/* Decrement SHLVL by 1 so a new shell started here has the same value,
preserving the appearance. After we do that, we need to change the
exported environment to include the new value. */
if (cleanenv == 0)
exported environment to include the new value. If we've already forked
and are in a subshell, we don't want to decrement the shell level,
since we are `increasing' the level */
if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0)
adjust_shell_level (-1);
if (cleanenv)
+1 -1
View File
@@ -59,7 +59,7 @@ $END
$BUILTIN readarray
$FUNCTION mapfile_builtin
$SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
$SHORT_DOC readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
Read lines from a file into an array variable.
A synonym for `mapfile'.
+5 -3
View File
@@ -711,8 +711,8 @@ printstr (fmt, string, len, fieldwidth, precision)
int fw, pr; /* fieldwidth and precision */
intmax_t mfw, mpr;
if (string == 0 || len == 0)
return 0;
if (string == 0)
string = "";
#if 0
s = fmt;
@@ -955,7 +955,9 @@ bexpand (string, len, sawc, lenp)
*sawc = 0;
if (lenp)
*lenp = 0;
return ((char *)NULL);
ret = (char *)xmalloc (1);
ret[0] = '\0';
return (ret);
}
ret = (char *)xmalloc (len + 1);
+12 -4
View File
@@ -859,7 +859,7 @@ unset_builtin (list)
#if defined (ARRAY_VARS)
unset_array = 0;
if (!unset_function && nameref == 0 && valid_array_reference (name, 0))
if (!unset_function && nameref == 0 && valid_array_reference (name, 1)) /* XXX valid array reference second arg was 0 */
{
t = strchr (name, '[');
*t++ = '\0';
@@ -916,7 +916,11 @@ unset_builtin (list)
if (var && unset_array)
{
/* Let unbind_array_element decide what to do with non-array vars */
tem = unbind_array_element (var, t);
#if 0
tem = unbind_array_element (var, t, 1); /* XXX new third arg */
#else
tem = unbind_array_element (var, t, 0); /* XXX new third arg */
#endif
if (tem == -2 && array_p (var) == 0 && assoc_p (var) == 0)
{
builtin_error (_("%s: not an array variable"), var->name);
@@ -938,8 +942,12 @@ unset_builtin (list)
if (valid_array_reference (nameref_cell (var), 0))
{
tname = savestring (nameref_cell (var));
if (var = array_variable_part (tname, &t, 0))
tem = unbind_array_element (var, t);
if (var = array_variable_part (tname, &t, (int *)0))
#if 0
tem = unbind_array_element (var, t, 1); /* XXX new third arg */
#else
tem = unbind_array_element (var, t, 0); /* XXX new third arg */
#endif
free (tname);
}
else
+1 -1
View File
@@ -3202,7 +3202,7 @@ format that can be reused as input.
.TP
.B E
The expansion is a string that is the value of \fIparameter\fP with backslash
escape sequences expanded as with the \fB$'...'\fP quoting mechansim.
escape sequences expanded as with the \fB$'...'\fP quoting mechanism.
.TP
.B P
The expansion is a string that is the result of expanding the value of
+5 -2
View File
@@ -1532,11 +1532,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
set_sigint_handler ();
#if defined (JOB_CONTROL)
/* Delete all traces that there were any jobs running. This is
only for subshells. */
without_job_control ();
#endif /* JOB_CONTROL */
if (fds_to_close)
close_fd_bitmap (fds_to_close);
@@ -5162,6 +5160,11 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
if (command)
{
/* If we're optimizing out the fork (implicit `exec'), decrement the
shell level like `exec' would do. */
if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
adjust_shell_level (-1);
maybe_make_export_env ();
put_command_name_into_env (command);
}
+1 -1
View File
@@ -1267,7 +1267,7 @@ readtok ()
#if defined (ARRAY_VARS)
if (c == '[')
{
e = skipsubscript (cp, 0, 0);
e = skipsubscript (cp, 0, 1); /* XXX - arg 3 was 0 */
if (cp[e] == ']')
{
cp += e + 1;
+4
View File
@@ -2866,6 +2866,10 @@ if (job == NO_JOB)
loop. */
else if (signal_is_trapped (SIGINT) && loop_level)
ADDINTERRUPT;
/* If an interactive shell with job control enabled is sourcing
a file, allow the interrupt to terminate the file sourcing. */
else if (interactive_shell && signal_is_trapped (SIGINT) == 0 && sourcelevel)
ADDINTERRUPT;
else
{
putchar ('\n');
+2 -2
View File
@@ -390,10 +390,10 @@ xstrmatch (pattern, string, flags)
wchar_t *wpattern, *wstring;
size_t plen, slen, mplen, mslen;
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
if (MB_CUR_MAX == 1)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
if (MB_CUR_MAX == 1)
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
n = xdupmbstowcs (&wpattern, NULL, pattern);
+5 -1
View File
@@ -57,6 +57,8 @@ extern int errno;
/* How big to make the_history when we first allocate it. */
#define DEFAULT_HISTORY_INITIAL_SIZE 502
#define MAX_HISTORY_INITIAL_SIZE 8192
/* The number of slots to increase the_history by. */
#define DEFAULT_HISTORY_GROW_SIZE 50
@@ -307,7 +309,9 @@ add_history (string)
if (history_size == 0)
{
if (history_stifled && history_max_entries > 0)
history_size = history_max_entries + 2;
history_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
? MAX_HISTORY_INITIAL_SIZE
: history_max_entries + 2;
else
history_size = DEFAULT_HISTORY_INITIAL_SIZE;
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+15
View File
@@ -49,6 +49,8 @@
#include "rlprivate.h"
#include "xmalloc.h"
#define MAX_MACRO_LEVEL 16
/* **************************************************************** */
/* */
/* Hacking Keyboard Macros */
@@ -83,12 +85,21 @@ struct saved_macro {
/* The list of saved macros. */
static struct saved_macro *macro_list = (struct saved_macro *)NULL;
static int macro_level = 0;
/* Set up to read subsequent input from STRING.
STRING is free ()'ed when we are done with it. */
void
_rl_with_macro_input (string)
char *string;
{
if (macro_level > MAX_MACRO_LEVEL)
{
_rl_errmsg ("maximum macro execution nesting level exceeded");
_rl_abort_internal ();
return;
}
_rl_push_executing_macro ();
rl_executing_macro = string;
executing_macro_index = 0;
@@ -146,6 +157,8 @@ _rl_push_executing_macro ()
saver->string = rl_executing_macro;
macro_list = saver;
macro_level++;
}
/* Discard the current macro, replacing it with the one
@@ -168,6 +181,8 @@ _rl_pop_executing_macro ()
xfree (macro);
}
macro_level--;
if (rl_executing_macro == 0)
RL_UNSETSTATE(RL_STATE_MACROINPUT);
}
+35 -11
View File
@@ -744,14 +744,14 @@ command: simple_command
COMMAND *tc;
tc = $1;
if (tc->redirects)
if (tc && tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $2;
}
else
else if (tc)
tc->redirects = $2;
$$ = $1;
}
@@ -830,21 +830,25 @@ for_command: FOR WORD newline_list DO compound_list DONE
arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
{
$$ = make_arith_for_command ($2, $6, arith_for_lineno);
/* if ($$ == 0) YYERROR; */
if (word_top > 0) word_top--;
}
| FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
{
$$ = make_arith_for_command ($2, $6, arith_for_lineno);
/* if ($$ == 0) YYERROR; */
if (word_top > 0) word_top--;
}
| FOR ARITH_FOR_EXPRS DO compound_list DONE
{
$$ = make_arith_for_command ($2, $4, arith_for_lineno);
/* if ($$ == 0) YYERROR; */
if (word_top > 0) word_top--;
}
| FOR ARITH_FOR_EXPRS '{' compound_list '}'
{
$$ = make_arith_for_command ($2, $4, arith_for_lineno);
/* if ($$ == 0) YYERROR; */
if (word_top > 0) word_top--;
}
;
@@ -928,14 +932,14 @@ function_body: shell_command
redirection. The two are semantically equivalent,
though -- the only difference is in how the
command printing code displays the redirections. */
if (tc->redirects)
if (tc && tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $2;
}
else
else if (tc)
tc->redirects = $2;
$$ = $1;
}
@@ -958,14 +962,14 @@ coproc: COPROC shell_command
COMMAND *tc;
tc = $2;
if (tc->redirects)
if (tc && tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $3;
}
else
else if (tc)
tc->redirects = $3;
$$ = make_coproc_command ("COPROC", $2);
$$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
@@ -980,14 +984,14 @@ coproc: COPROC shell_command
COMMAND *tc;
tc = $3;
if (tc->redirects)
if (tc && tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $4;
}
else
else if (tc)
tc->redirects = $4;
$$ = make_coproc_command ($2->word, $3);
$$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
@@ -4512,7 +4516,7 @@ cond_term ()
if (term)
term->flags |= CMD_INVERT_RETURN;
}
else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[1] && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
{
op = yylval.word;
tok = read_token (READ);
@@ -4651,14 +4655,34 @@ token_is_assignment (t, i)
char *t;
int i;
{
unsigned char c, c1;
int r;
#if !defined (USING_BASH_MALLOC)
static char *token = 0;
token = xrealloc (token, i + 3);
memcpy (token, t, i);
token[i] = '=';
token[i+1] = '\0';
r = assignment (token, (parser_state & PST_COMPASSIGN) != 0);
if (i + 3 > 4096) /* keep it from getting too big */
{
free (token);
token = 0;
}
#else
unsigned char c, c1;
c = t[i]; c1 = t[i+1];
t[i] = '='; t[i+1] = '\0';
r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
t[i] = c; t[i+1] = c1;
return r;
#endif
/* XXX - check that r == i to avoid returning false positive for
t containing `=' before t[i]. */
return (r > 0 && r == i);
}
/* XXX - possible changes here for `+=' */
+147 -293
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1683,7 +1683,8 @@ unquote_bang (string)
parse array subscripts. FLAGS & 1 means to not attempt to skip over
matched pairs of quotes or backquotes, or skip word expansions; it is
intended to be used after expansion has been performed and during final
assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
assignment parsing (see arrayfunc.c:assign_compound_array_list()) or
during execution by a builtin which has already undergone word expansion. */
static int
skip_matched_pair (string, start, open, close, flags)
const char *string;
@@ -1712,7 +1713,7 @@ skip_matched_pair (string, start, open, close, flags)
ADVANCE_CHAR (string, slen, i);
continue;
}
else if (c == '\\')
else if ((flags & 1) == 0 && c == '\\')
{
pass_next = 1;
i++;
+1 -1
View File
@@ -670,7 +670,7 @@ test_binop (op)
else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!'))
return (1);
#endif
else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0')
else if (op[0] != '-' || op[1] == '\0' || op[2] == '\0' || op[3] != '\0')
return (0);
else
{
+1 -1
View File
@@ -1,4 +1,4 @@
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
+4 -4
View File
@@ -20,7 +20,7 @@ jkl mno
fff is a function
fff ()
{
ed /tmp/foo > /dev/null <<ENDOFINPUT
ed /tmp/foo <<ENDOFINPUT > /dev/null
/^name/d
w
q
@@ -31,7 +31,7 @@ ENDOFINPUT
fff is a function
fff ()
{
ed /tmp/foo > /dev/null <<ENDOFINPUT
ed /tmp/foo <<ENDOFINPUT > /dev/null
/^name/d
w
q
@@ -43,11 +43,11 @@ foo is a function
foo ()
{
echo;
cat <<END
cat <<END
bar
END
cat <<EOF
cat <<EOF
qux
EOF
+1
View File
@@ -148,6 +148,7 @@ b
xx
xx
< >< >
one
one\ctwo
4\.2
+3 -1
View File
@@ -308,6 +308,9 @@ shopt -s nullglob extglob
echo "x$(printf "%b" @(hugo))x"
printf -v var "%b" @(hugo); echo "x${var}x"
# make sure that missing arguments are always handled like the empty string
printf "<%3s><%3b>\n"
# tests variable assignment with -v
${THIS_SH} ./printf1.sub
@@ -316,4 +319,3 @@ ${THIS_SH} ./printf2.sub
${THIS_SH} ./printf3.sub
${THIS_SH} ./printf4.sub
+7 -7
View File
@@ -65,11 +65,11 @@ foo is a function
foo ()
{
echo;
cat <<END
cat <<END
bar
END
cat <<EOF
cat <<EOF
qux
EOF
@@ -86,7 +86,7 @@ foo ()
rm -f a b c;
for f in a b c;
do
cat >> ${f} <<-EOF
cat <<-EOF >> ${f}
file
EOF
@@ -99,7 +99,7 @@ c:file
bb is a function
bb ()
{
( cat <<EOF
( cat <<EOF
foo
bar
EOF
@@ -110,13 +110,13 @@ mkcoprocs is a function
mkcoprocs ()
{
coproc a {
cat <<EOF1
cat <<EOF1
producer 1
EOF1
}
coproc b {
cat <<EOF2
cat <<EOF2
producer 2
EOF2
@@ -126,7 +126,7 @@ EOF2
mkcoprocs is a function
mkcoprocs ()
{
coproc COPROC ( b cat <<EOF
coproc COPROC ( b cat <<EOF
heredoc
body
EOF
+1 -1
View File
@@ -27,7 +27,7 @@ line 3
bar is a function
bar ()
{
exec {v}<<EOF
exec {v}<<EOF
line 1
line 2
line 3
+2 -2
View File
@@ -3030,7 +3030,7 @@ bind_int_variable (lhs, rhs)
v = bind_array_variable (lhs, 0, rhs, 0);
else
#endif
v = bind_variable (lhs, rhs, 0);
v = bind_variable (lhs, rhs, 0); /* why not use bind_variable_value? */
if (v)
{
@@ -3960,7 +3960,7 @@ static int
visible_array_vars (var)
SHELL_VAR *var;
{
return (invisible_p (var) == 0 && array_p (var));
return (invisible_p (var) == 0 && (array_p (var) || assoc_p (var)));
}
SHELL_VAR **