Failing shell code under busybox 1.36.1 that worked with 1.31.1
Harvey
harv at gmx.de
Thu Feb 15 21:48:42 UTC 2024
David,
I can confirm that your patch solves my problem without any further need
to change the shell code. Now V 1.36.1 acts in the same way as V 1.31.1
did. Thank you so mutch! Maybe this is candidate to merge ;)
Greetings
Harvey
Am 15.02.24 um 09:45 schrieb David Leonard:
>
>> _result="$_result '${_p//'/'\"'\"'}'"
>
> Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
> replacement behaviour. And, in bash, the ' in the pattern section is
> treated
> as a quote start. To give the ' a literal meaning, use \'
> eg ${_p//\'/..repl..}
>
> In current busybox ash you will run into a bug where quotes aren't
> handled in the pattern, and even loses the rest of the word, as you
> observed. That is, given this script:
>
> var="don't g/o"
> echo "${var/'/'o}!"
> echo "${var/\'/\'o}!"
>
> bash outputs:
>
> don't g! (pattern="/o" repl="")
> don'ot g/o! (pattern="'", repl="'o")
>
> and busybox ash outputs:
>
> don't g/o (pattern=?, repl=?, NOTE: lost !)
> don'ot g/o! (pattern="'", repl="'o")
>
> Here's a patch to make ash a little bit closer to bash.
>
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -7058,6 +7058,7 @@ subevalvar(char *start, char *str, int strloc,
> */
> repl = NULL;
> if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
> + int quoted = 0;
> /* Find '/' and replace with NUL */
> repl = start;
> /* The pattern can't be empty.
> @@ -7073,6 +7074,11 @@ subevalvar(char *start, char *str, int strloc,
> repl = NULL;
> break;
> }
> + /* Handle quoted patterns */
> + if ((unsigned char)*repl == CTLQUOTEMARK)
> + quoted ^= 1;
> + if (quoted)
> + goto literal;
> if (*repl == '/') {
> *repl = '\0';
> break;
> @@ -7084,6 +7090,7 @@ subevalvar(char *start, char *str, int strloc,
> /* Handle escaped slashes, e.g. "${v/\//_}"
> (they are CTLESC'ed by this point) */
> if ((unsigned char)*repl == CTLESC && repl[1])
> repl++;
> + literal:
> repl++;
> }
> }
>
> new file mode 100644
> index 000000000..23aecb5ae
> --- /dev/null
> +++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.right
> @@ -0,0 +1,3 @@
> +ab.
> +axb.
> +x/b.
> new file mode 100644
> index 000000000..d2ba39578
> --- /dev/null
> +++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.tests
> @@ -0,0 +1,4 @@
> +v=a/b
> +echo "${v/'/'}."
> +echo "${v/'/'/x}."
> +echo "${v/'a'/x}."
>
>
>
> On Wed, 14 Feb 2024, Harvey wrote:
>
>> Sorry, posted the wrong version of the pack_args() funtion:
>> I have payed with possible solutions for so long that I forgot the
>> restore the original before posting -blush-
>>
>> Here is the original version:
>> ------------------------------------------------------------------------
>>
>> # Packs arguments into a single string.
>> #
>> # Input:
>> # $1 = name of variable receiving the arguments in such a way that
>> # (re)evaluating them provides the original arguments
>> # $2... = arguments
>> # Example:
>> # func() {
>> # local args
>> # pack_args args "$@"
>> # send_rpc func_impl "$args"
>> # }
>> # # (in another process) > # receive_rpc() {
>> # local func="$1"
>> # local args="$2"
>> # eval $func "$args"
>> # }
>> pack_args()
>> {
>> local _p _resvar=$1 _result= _value
>> shift
>> for _p
>> do
>> _result="$_result '${_p//'/'\"'\"'}'"
>> done
>> eval $_resvar=\${_result\# }
>> }
>> ------------------------------------------------------------------------
>>
>> Harvey
>>
>> Am 14.02.24 um 19:06 schrieb Harvey:
>>> Hello,
>>>
>>> I am part of the team of a small router distribution called fli4l:
>>> https://www.fli4l.de/doku.php?id=start.
>>>
>>> We use buildroot to generate our images. Due to a hardware crash and the
>>> leaving of our main developer we are facing the dead of our project. But
>>> there are still some people left and at least we want to try to keep it
>>> alive 😉
>>>
>>> That said - the first we have to try is the update of our buildroot
>>> base. A lot of work is already done and but we struggle with the busybox
>>> update, especially with the ash shell contained. When updating to
>>> Version 1.36.1 we are facing script failures in places that did work
>>> until busybox 1.31.1.
>>>
>>> I have tried to debug the code and it seems that the error is contained
>>> in a helper include for string handling.
>>>
>>> The code is:
>>> ------------------------------------------------------------------------
>>> # Packs arguments into a single string.
>>> #
>>> # Input:
>>> # $1 = name of variable receiving the arguments in such a way that
>>> # (re)evaluating them provides the original arguments
>>> # $2... = arguments
>>> # Example:
>>> # func() {
>>> # local args
>>> # pack_args args "$@"
>>> # send_rpc func_impl "$args"
>>> # }
>>> # # (in another process)
>>> # receive_rpc() {
>>> # local func="$1"
>>> # local args="$2"
>>> # eval $func "$args"
>>> # }
>>> pack_args()
>>> {
>>> local _p _resvar=$1 _result= _value
>>> shift
>>> for _p
>>> do
>>> _result="$_result '${_p//'/'\"'\"'}''"
>>> done
>>> eval $_resvar=\${_result\# }
>>> }
>>> ------------------------------------------------------------------------
>>>
>>> The debug trace (using set -x) in V1.31.1 looks like this:
>>>
>>> + pack_args exit_trap_0 sync_unlock_all_resources
>>> + local _p '_resvar=exit_trap_0' '_result=' _value
>>> + shift
>>> + _result=' '"'"'sync_unlock_all_resources'"'"
>>> + eval 'exit_trap_0=${_result#' '}'
>>> + exit_trap_0=''"'"'sync_unlock_all_resources'"'"
>>> + exit_trap_num=1
>>> + return 0
>>>
>>> ------------------------------------------------------------------------
>>> while in V1.36.1 it looks like this:
>>>
>>> + pack_args exit_trap_0 sync_unlock_all_resources
>>> + local _p '_resvar=exit_trap_0' '_result=' _value
>>> + shift
>>> + _result=' '"'"'sync_unlock_all_resources'
>>> ^^^^ missing quote
>>> + eval 'exit_trap_0=${_result#' '}'
>>> + exit_trap_0=''"'"'sync_unlock_all_resources'
>>> ^^^^ missing quote
>>> + exit_trap_num=1
>>> + return 0
>>>
>>> The eval line then fails with 'Unterminated quoted string'
>>>
>>> Unfortunately I can't tell where the difference lies.
>>>
>>> I hope someone can help or at least point me in the right direction.
>>>
>>> Greetings
>>> Harvey
>>> _______________________________________________
>>> busybox mailing list
>>> busybox at busybox.net
>>> http://lists.busybox.net/mailman/listinfo/busybox
>> _______________________________________________
>> busybox mailing list
>> busybox at busybox.net
>> http://lists.busybox.net/mailman/listinfo/busybox
>>
More information about the busybox
mailing list