Remove "Array index out of bounds" errors

This just removes every invalid index.

That means with `set foo a b c` and the "show" function from tests/expand.in:

- `show $foo[-5..-1]` prints "3 a b c"
- `show $foo[-10..1]` prints "1 a"
- `show $foo[2..5]` prints "2 b c"
- `show $foo[1 3 7 2]` prints "3 a c b"

and similar for command substitutions.

Fixes #826.
This commit is contained in:
Fabian Homborg 2017-04-07 21:48:44 +02:00 committed by Kurtis Rader
parent df01547eab
commit 44f2f37bd4
4 changed files with 32 additions and 54 deletions

View file

@ -796,29 +796,22 @@ static int expand_variables(const wcstring &instr, std::vector<completion_t> *ou
if (!all_vars) { if (!all_vars) {
wcstring_list_t string_values(var_idx_list.size()); wcstring_list_t string_values(var_idx_list.size());
size_t k = 0;
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);
// Check that we are within array bounds. If not, truncate the list to // Check that we are within array bounds. If not, skip the element. Note:
// exit. // Negative indices (`echo $foo[-1]`) are already converted to positive ones
if (tmp < 1 || (size_t)tmp > var_item_list.size()) { // here, So tmp < 1 means it's definitely not in.
size_t var_src_pos = var_pos_list.at(j); if ((size_t)tmp > var_item_list.size() || tmp < 1) {
// The slice was parsed starting at stop_pos, so we have to add that continue;
// to the error position.
append_syntax_error(errors, slice_start + var_src_pos,
ARRAY_BOUNDS_ERR);
is_ok = false;
var_idx_list.resize(j);
break;
} else {
// Replace each index in var_idx_list inplace with the string value
// at the specified index.
// al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get(
// &var_item_list, tmp-1 ) ) );
string_values.at(j) = var_item_list.at(tmp - 1);
} }
// Replace each index in var_idx_list inplace with the string value
// at the specified index.
string_values.at(k++) = var_item_list.at(tmp - 1);
} }
// string_values is the new var_item_list. // string_values is the new var_item_list. Resize to remove invalid elements.
string_values.resize(k);
var_item_list = std::move(string_values); var_item_list = std::move(string_values);
} }
} }
@ -892,17 +885,6 @@ static int expand_variables(const wcstring &instr, std::vector<completion_t> *ou
return is_ok; return is_ok;
} }
stop_pos = (slice_end - in); 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.
@ -1090,10 +1072,8 @@ static int expand_cmdsubst(const wcstring &input, std::vector<completion_t> *out
tail_begin = slice_end; tail_begin = slice_end;
for (i = 0; i < slice_idx.size(); i++) { for (i = 0; i < slice_idx.size(); i++) {
long idx = slice_idx.at(i); long idx = slice_idx.at(i);
if (idx < 1 || (size_t)idx > sub_res.size()) { if ((size_t)idx > sub_res.size() || idx < 1) {
size_t pos = slice_source_positions.at(i); continue;
append_syntax_error(errors, slice_begin - in + pos, ARRAY_BOUNDS_ERR);
return 0;
} }
idx = idx - 1; idx = idx - 1;

View file

@ -1,30 +1,9 @@
fish: Array index out of bounds
show "$foo[2]"
^
fish: Array index out of bounds
show $foo[2]
^
fish: Array index out of bounds
show "$foo[1 2]"
^
fish: Array index out of bounds
show $foo[1 2]
^
fish: Array index out of bounds
show "$foo[2 1]"
^
fish: Array index out of bounds
show $foo[2 1]
^
fish: Invalid index value fish: Invalid index value
echo "$foo[d]" echo "$foo[d]"
^ ^
fish: Invalid index value fish: Invalid index value
echo $foo[d] echo $foo[d]
^ ^
fish: Array index out of bounds
echo ()[1]
^
fish: Invalid index value fish: Invalid index value
echo ()[d] echo ()[d]
^ ^

View file

@ -62,6 +62,12 @@ show "$$foo"
show $$foo show $$foo
show "prefix$$foo" show "prefix$$foo"
show prefix$$foo show prefix$$foo
show $foo[-5..2]
show $foo[-2..-1]
show $foo[-10..-5]
show (printf '%s\n' $foo)[-5..2]
show (printf '%s\n' $foo)[-2..-1]
show (printf '%s\n' $foo)[-10..-5]
set -l foo set -l foo
show "$foo[1]" show "$foo[1]"

View file

@ -36,8 +36,21 @@
2 baz quux 2 baz quux
1 prefixbaz quux fooest 1 prefixbaz quux fooest
2 prefixbaz prefixquux 2 prefixbaz prefixquux
2 bar
2 fooest
0
2 bar
2 fooest
0
1
0
1 1
0 0
1 1
0 0
1
0
1
0
Catch your breath Catch your breath