aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expand.cpp31
-rw-r--r--tests/expansion.err12
-rw-r--r--tests/expansion.in6
3 files changed, 39 insertions, 10 deletions
diff --git a/expand.cpp b/expand.cpp
index 7388cb18..5f96fb2f 100644
--- a/expand.cpp
+++ b/expand.cpp
@@ -953,8 +953,11 @@ void expand_variable_error(parser_t &parser, const wcstring &token, size_t token
/**
Parse an array slicing specification
+ Returns 0 on success.
+ If a parse error occurs, returns the index of the bad token.
+ Note that 0 can never be a bad index because the string always starts with [.
*/
-static int parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, std::vector<size_t> &source_positions, size_t array_size)
+static size_t parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, std::vector<size_t> &source_positions, size_t array_size)
{
wchar_t *end;
@@ -981,7 +984,7 @@ static int parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long> &
tmp = wcstol(&in[pos], &end, 10);
if ((errno) || (end == &in[pos]))
{
- return 1;
+ return pos;
}
// debug( 0, L"Push idx %d", tmp );
@@ -999,7 +1002,7 @@ static int parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long> &
long tmp1 = wcstol(&in[pos], &end, 10);
if ((errno) || (end == &in[pos]))
{
- return 1;
+ return pos;
}
pos = end-in;
@@ -1136,12 +1139,14 @@ static int expand_variables_internal(parser_t &parser, wchar_t * const in, std::
if (in[slice_start] == L'[')
{
wchar_t *slice_end;
+ size_t bad_pos;
all_vars=0;
- if (parse_slice(in + slice_start, &slice_end, var_idx_list, var_pos_list, var_item_list.size()))
+ bad_pos = parse_slice(in + slice_start, &slice_end, var_idx_list, var_pos_list, var_item_list.size());
+ if (bad_pos != 0)
{
append_syntax_error(errors,
- stop_pos,
+ stop_pos + bad_pos,
L"Invalid index value");
is_ok = 0;
break;
@@ -1261,11 +1266,13 @@ static int expand_variables_internal(parser_t &parser, wchar_t * const in, std::
if (in[slice_start] == L'[')
{
wchar_t *slice_end;
+ size_t bad_pos;
- if (parse_slice(in + slice_start, &slice_end, var_idx_list, var_pos_list, 1))
+ bad_pos = parse_slice(in + slice_start, &slice_end, var_idx_list, var_pos_list, 1);
+ if (bad_pos != 0)
{
append_syntax_error(errors,
- stop_pos,
+ stop_pos + bad_pos,
L"Invalid index value");
is_ok = 0;
return is_ok;
@@ -1499,11 +1506,14 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<
{
std::vector<long> slice_idx;
std::vector<size_t> slice_source_positions;
+ const wchar_t * const slice_begin = tail_begin;
wchar_t *slice_end;
+ size_t bad_pos;
- if (parse_slice(tail_begin, &slice_end, slice_idx, slice_source_positions, sub_res.size()))
+ bad_pos = parse_slice(slice_begin, &slice_end, slice_idx, slice_source_positions, sub_res.size());
+ if (bad_pos != 0)
{
- append_syntax_error(errors, SOURCE_LOCATION_UNKNOWN, L"Invalid index value");
+ append_syntax_error(errors, slice_begin - in + bad_pos, L"Invalid index value");
return 0;
}
else
@@ -1515,8 +1525,9 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<
long idx = slice_idx.at(i);
if (idx < 1 || (size_t)idx > sub_res.size())
{
+ size_t pos = slice_source_positions.at(i);
append_syntax_error(errors,
- SOURCE_LOCATION_UNKNOWN,
+ slice_begin - in + pos,
ARRAY_BOUNDS_ERR);
return 0;
}
diff --git a/tests/expansion.err b/tests/expansion.err
index 6346f23f..e60c203d 100644
--- a/tests/expansion.err
+++ b/tests/expansion.err
@@ -16,3 +16,15 @@ fish: show "$foo[2 1]"
Array index out of bounds
fish: show $foo[2 1]
^
+Invalid index value
+fish: echo "$foo[d]"
+ ^
+Invalid index value
+fish: echo $foo[d]
+ ^
+Array index out of bounds
+fish: echo ()[1]
+ ^
+Invalid index value
+fish: echo ()[d]
+ ^
diff --git a/tests/expansion.in b/tests/expansion.in
index 8b48772e..a2225127 100644
--- a/tests/expansion.in
+++ b/tests/expansion.in
@@ -74,3 +74,9 @@ show "$foo[1 2]"
show $foo[1 2]
show "$foo[2 1]"
show $foo[2 1]
+
+echo "$foo[d]"
+echo $foo[d]
+
+echo ()[1]
+echo ()[d]