Parse slices even for empty variables

When a variable is parsed as being empty, parse out the slice and
validate the indexes anyway, behaving for slicing purposes as if the
variable had a single empty value.

Besides providing errors when expected, this also fixes the following:

    set -l foo
    echo "$foo[1]"

This used to print "[1]", now it properly prints nothing.
This commit is contained in:
Kevin Ballard 2014-08-20 22:01:24 -07:00
parent 3981b644d6
commit cc49042294
4 changed files with 68 additions and 1 deletions

View file

@ -1155,10 +1155,10 @@ static int expand_variables_internal(parser_t &parser, wchar_t * const in, std::
for (size_t j=0; j<var_idx_list.size(); j++) for (size_t j=0; j<var_idx_list.size(); j++)
{ {
long tmp = var_idx_list.at(j); long tmp = var_idx_list.at(j);
size_t var_src_pos = var_pos_list.at(j);
/* Check that we are within array bounds. If not, truncate the list to exit. */ /* Check that we are within array bounds. If not, truncate the list to exit. */
if (tmp < 1 || (size_t)tmp > var_item_list.size()) if (tmp < 1 || (size_t)tmp > var_item_list.size())
{ {
size_t var_src_pos = var_pos_list.at(j);
/* The slice was parsed starting at stop_pos, so we have to add that to the error position */ /* The slice was parsed starting at stop_pos, so we have to add that to the error position */
append_syntax_error(errors, append_syntax_error(errors,
slice_start + var_src_pos, slice_start + var_src_pos,
@ -1255,6 +1255,39 @@ static int expand_variables_internal(parser_t &parser, wchar_t * const in, std::
} }
else else
{ {
// even with no value, we still need to parse out slice syntax
// Behave as though we had 1 value, so $foo[1] always works.
const size_t slice_start = stop_pos;
if (in[slice_start] == L'[')
{
wchar_t *slice_end;
if (parse_slice(in + slice_start, &slice_end, var_idx_list, var_pos_list, 1))
{
append_syntax_error(errors,
stop_pos,
L"Invalid index value");
is_ok = 0;
return is_ok;
}
stop_pos = (slice_end-in);
// validate that the parsed indexes are valid
for (size_t j=0; j<var_idx_list.size(); j++)
{
long tmp = var_idx_list.at(j);
if (tmp != 1)
{
size_t var_src_pos = var_pos_list.at(j);
append_syntax_error(errors,
slice_start + var_src_pos,
ARRAY_BOUNDS_ERR);
is_ok = 0;
return is_ok;
}
}
}
/* /*
Expand a non-existing variable Expand a non-existing variable
*/ */

View file

@ -0,0 +1,18 @@
Array index out of bounds
fish: show "$foo[2]"
^
Array index out of bounds
fish: show $foo[2]
^
Array index out of bounds
fish: show "$foo[1 2]"
^
Array index out of bounds
fish: show $foo[1 2]
^
Array index out of bounds
fish: show "$foo[2 1]"
^
Array index out of bounds
fish: show $foo[2 1]
^

View file

@ -62,3 +62,15 @@ show "$$foo"
show $$foo show $$foo
show "prefix$$foo" show "prefix$$foo"
show prefix$$foo show prefix$$foo
set -l foo
show "$foo[1]"
show $foo[1]
show "$foo[-1]"
show $foo[-1]
show "$foo[2]"
show $foo[2]
show "$foo[1 2]"
show $foo[1 2]
show "$foo[2 1]"
show $foo[2 1]

View file

@ -36,3 +36,7 @@
2 baz quux 2 baz quux
1 prefixbaz quux fooest 1 prefixbaz quux fooest
2 prefixbaz prefixquux 2 prefixbaz prefixquux
1
0
1
0