alicelinux

A lightweight musl + clang/llvm + libressl + busybox distro
git clone https://codeberg.org/emmett1/alicelinux
Log | Files | Refs | README | LICENSE

0001-awk-fix-handling-of-literal-backslashes-in-replaceme.patch (2187B)


      1 From c281b87c89918c05eddbb1101fb87999437a2505 Mon Sep 17 00:00:00 2001
      2 From: Yao Zi <ziyao@disroot.org>
      3 Date: Thu, 14 Nov 2024 11:11:50 +0000
      4 Subject: [PATCH] awk: fix handling of literal backslashes in replacement
      5 
      6 According to POSIX standard, a backslash in the replacement of sub()
      7 should be treated as a literal backslash if it is not preceded by a '&'
      8 or another backslash. But busybox awk skips it unconditionally,
      9 regardless of the following character. For example,
     10 
     11   $ echo "abc" | busybox awk 'sub(/abc/, "\\d")'
     12   d
     13 
     14 where \d is expected here. This is known to break rsync's documentation
     15 converter.
     16 
     17 Let's check the next character before skipping the backslash, following
     18 POSIX standard and behavior of GNU awk.
     19 
     20 Link: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html
     21 Link: https://github.com/RsyncProject/rsync/blob/62bb9bba022ce6a29f8c92307d5569c338b2f711/help-from-md.awk#L22
     22 Fixes: 5f84c5633 ("awk: fix backslash handling in sub() builtins")
     23 Signed-off-by: Yao Zi <ziyao@disroot.org>
     24 ---
     25  editors/awk.c       | 7 ++++++-
     26  testsuite/awk.tests | 5 +++++
     27  2 files changed, 11 insertions(+), 1 deletion(-)
     28 
     29 diff --git a/editors/awk.c b/editors/awk.c
     30 index 64e752f4b..40f5ba7f7 100644
     31 --- a/editors/awk.c
     32 +++ b/editors/awk.c
     33 @@ -2636,8 +2636,13 @@ static int awk_sub(node *rn, const char *repl, int nm, var *src, var *dest /*,in
     34  					resbuf = qrealloc(resbuf, residx + replen + n, &resbufsize);
     35  					memcpy(resbuf + residx, sp + pmatch[j].rm_so - start_ofs, n);
     36  					residx += n;
     37 -				} else
     38 +				} else {
     39 +/* '\\' and '&' following a backslash keep its original meaning, any other
     40 + * occurrence of a '\\' should be treated as literal */
     41 +					if (bslash && c != '\\' && c != '&')
     42 +						resbuf[residx++] = '\\';
     43  					resbuf[residx++] = c;
     44 +				}
     45  				bslash = 0;
     46  			}
     47  		}
     48 diff --git a/testsuite/awk.tests b/testsuite/awk.tests
     49 index be25f6696..61b3bc7d6 100755
     50 --- a/testsuite/awk.tests
     51 +++ b/testsuite/awk.tests
     52 @@ -617,4 +617,9 @@ testing 'awk gsub erroneous word start match' \
     53  	'abc\n' \
     54  	'' ''
     55  
     56 +testing 'awk sub literal backslash in replacement' \
     57 +	'awk '$sq'sub(/abc/, "\\\d")'$sq \
     58 +	'\d\n' \
     59 +	'' 'abc\n'
     60 +
     61  exit $FAILCOUNT
     62 -- 
     63 2.47.1
     64