[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] 4.0..devel: fix a problem that unset 'a[`echo 0`]' causes "bad a
From: |
Koichi Murase |
Subject: |
[PATCH] 4.0..devel: fix a problem that unset 'a[`echo 0`]' causes "bad array subscript" error |
Date: |
Wed, 6 Oct 2021 11:48:32 +0900 |
[ I initially intended to submit this report after the previous report
at https://lists.gnu.org/archive/html/bug-bash/2021-10/msg00051.html
has been settled. I decided to submit this patch now because a
problem related to this report is mentioned in the above thread. Note
that this patch bases on the code after applying the patches provided
at the previous report. ]
Bash Version:
All the versions from 4.0 to devel are affected. The problem should
be reproduced independent of the machine type.
Description:
« unset -v 'a[`echo 0`]' » fails because the first character « ` »
of the subscript « `echo 0` » is skipped when checking the ending of
the array subscript.
This is caused by the mismatching of the assumptions on the
arguments of `unbind_array_reference (var,sub,flags)' and
`skipsubscript (string,start,flags)'. The former assumes `sub'
starts from the next character after `[` while the latter assumes
that `string[start]' starts from `[` itself. However,
`unbind_array_reference' directly passes `sub' to `skipsubscript'.
Repeat-By:
$ bash -c "a=(); unset 'a[\`echo [0]\`]'"
bash: line 0: unset: a[`echo [0]`]: bad array subscript
This is caused by the mismatching of the assumption on the argument
of `unbind_array_reference' (arrayfunc.c:1062) and the argument of
`skipsubscript' (subst.c:1845).
The function `unbind_array_reference' assumes that the second
argument SUB points to just after the beginning `[' as described in
the comment of the function (arrayfunc.c:1054):
> /* This function is called with SUB pointing to just after the beginning
> `[' 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, flags)
In this function, another function `skipsubscript' is called as
> len = skipsubscript (sub, 0, (flags&VA_NOEXPAND) | 2); /* XXX */
The function `skipsubscript' calls another function `skip_matched_pair'
(subst.c:1747).
> int
> skipsubscript (string, start, flags)
> const char *string;
> int start, flags;
> {
> return (skip_matched_pair (string, start, '[', ']', flags));
The function `skip_matched_pair' assumes that `string[start]' points
to the beginning `[' itself:
> /* This function assumes s[i] == open; returns with s[ret] == close; used to
> 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()) or
> during execution by a builtin which has already undergone word
expansion. */
> static int
> skip_matched_pair (string, start, open, close, flags)
which is inconsistent with the assumption of
`unbind_array_reference' that `sub' points to the next character of
the beginning `['.
Fix:
In the attached patch, I added a new flag 2 in the `flags` argument
of `skipsubscript', which indicates that `string[start]' points to
the next character after the beginning delimiter `open' (`[' in this
case).
Now, the bit `2' of the argument `flags' of `skipsubscript
(var,sub,flags)' will change the behavior. Also,
`array_variable_name (s,flags,subp,lenp)' and `array_variable_part
(s,flags,subp,lenp)' indirectly calls `skipsubscript' by directly
passing its argument `flags'. I have checked all the existing calls
of these functions and confirmed that currently the arguments are
always `0' or `1' and never contains the bit `2', so the existing
behavior will not change.
Then, I added the bit `2' in the call of `skipsubscript' from
`unbind_array_reference'. I also changed the argument `flags' of
the call of `skipsubscript' in `array_variable_name' with `flags &
1' because `array_variable_name' explicitly searches for the
beginning `[' and pass its position to `skipsubscript'.
I also updated the comments of the functions. If you think we
should define constants for these flags such as `#define
SKIPSUBSCRIPT_NONESTING 1' and `#define SKIPSUBSCRIPT_STARTAFTEROPEN
2', I can adjust the patch.
--
Koichi
0001-arrayfunc.c-unset_array_element-fix-a-bug-that-the-f.patch
Description: Binary data
- [PATCH] 4.0..devel: fix a problem that unset 'a[`echo 0`]' causes "bad array subscript" error,
Koichi Murase <=