[PATCH] awk: fix handling of literal backslashes in replacement

Natanael Copa ncopa at alpinelinux.org
Fri Dec 13 13:15:56 UTC 2024


Denys,

This is sort of important. In addition to mentioned issues it also fixes
kernel build and gcc cross compiler build with busybox awk.

I have tested this fix.

Can you please apply this and cherry-pick it for 1_37_stable?

Thank you Yao Zi and thank you Denys!

-nc


On Thu, 14 Nov 2024 11:11:50 +0000
Yao Zi <ziyao at disroot.org> wrote:

> According to POSIX standard, a backslash in the replacement of sub()
> should be treated as a literal backslash if it is not preceded by a '&'
> or another backslash. But busybox awk skips it unconditionally,
> regardless of the following character. For example,
> 
>   $ echo "abc" | busybox awk 'sub(/abc/, "\\d")'
>   d
> 
> where \d is expected here. This is known to break rsync's documentation
> converter.
> 
> Let's check the next character before skipping the backslash, following
> POSIX standard and behavior of GNU awk.
> 
> Link: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html
> Link: https://github.com/RsyncProject/rsync/blob/62bb9bba022ce6a29f8c92307d5569c338b2f711/help-from-md.awk#L22
> Fixes: 5f84c5633 ("awk: fix backslash handling in sub() builtins")
> Signed-off-by: Yao Zi <ziyao at disroot.org>

Acked-by: Natanael Copa <ncopa at alpinelinux.org>

Fixes: https://bugs.busybox.net/show_bug.cgi?id=16270
Fixes: https://github.com/raspberrypi/linux/issues/6503

> ---
>  editors/awk.c       | 7 ++++++-
>  testsuite/awk.tests | 5 +++++
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/editors/awk.c b/editors/awk.c
> index 64e752f4b..40f5ba7f7 100644
> --- a/editors/awk.c
> +++ b/editors/awk.c
> @@ -2636,8 +2636,13 @@ static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest /*,in
>  					resbuf = qrealloc(resbuf, residx + replen + n, &resbufsize);
>  					memcpy(resbuf + residx, sp + pmatch[j].rm_so - start_ofs, n);
>  					residx += n;
> -				} else
> +				} else {
> +/* '\\' and '&' following a backslash keep its original meaning, any other
> + * occurrence of a '\\' should be treated as literal */
> +					if (bslash && c != '\\' && c != '&')
> +						resbuf[residx++] = '\\';
>  					resbuf[residx++] = c;
> +				}
>  				bslash = 0;
>  			}
>  		}
> diff --git a/testsuite/awk.tests b/testsuite/awk.tests
> index be25f6696..61b3bc7d6 100755
> --- a/testsuite/awk.tests
> +++ b/testsuite/awk.tests
> @@ -617,4 +617,9 @@ testing 'awk gsub erroneous word start match' \
>  	'abc\n' \
>  	'' ''
>  
> +testing 'awk sub literal backslash in replacement' \
> +	'awk '$sq'sub(/abc/, "\\\d")'$sq \
> +	'\d\n' \
> +	'' 'abc\n'
> +
>  exit $FAILCOUNT



More information about the busybox mailing list