aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-01-27 11:19:14 +0000
committerDenys Vlasenko <vda.linux@googlemail.com>2021-02-02 13:51:14 +0100
commite8fe9f96356a6b19ec907ea30cffc829c539a7ff (patch)
tree1c9450cbdc4c32266241652303852acde28c14a0
parentf3a55b306ed3803133ab028b72b255c65d94197f (diff)
downloadbusybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.tar.gz
busybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.tar.bz2
busybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.zip
awk: allow printf('%c') to output NUL, closes 13486
Treat the output of printf as binary rather than a null-terminated string so that NUL characters can be output. This is considered to be a GNU extension, though it's also available in mawk and FreeBSD's awk. function old new delta evaluate 3487 3504 +17 awk_printf 504 519 +15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 32/0) Total: 32 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c18
-rwxr-xr-xtestsuite/awk.tests5
2 files changed, 20 insertions, 3 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 2c15f9e4e..b4f6a3741 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2155,7 +2155,10 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i
2155} 2155}
2156 2156
2157/* formatted output into an allocated buffer, return ptr to buffer */ 2157/* formatted output into an allocated buffer, return ptr to buffer */
2158static char *awk_printf(node *n) 2158#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2159# define awk_printf(a, b) awk_printf(a)
2160#endif
2161static char *awk_printf(node *n, int *len)
2159{ 2162{
2160 char *b = NULL; 2163 char *b = NULL;
2161 char *fmt, *s, *f; 2164 char *fmt, *s, *f;
@@ -2209,6 +2212,10 @@ static char *awk_printf(node *n)
2209 nvfree(v); 2212 nvfree(v);
2210 b = xrealloc(b, i + 1); 2213 b = xrealloc(b, i + 1);
2211 b[i] = '\0'; 2214 b[i] = '\0';
2215#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2216 if (len)
2217 *len = i;
2218#endif
2212 return b; 2219 return b;
2213} 2220}
2214 2221
@@ -2666,6 +2673,7 @@ static var *evaluate(node *op, var *res)
2666 case XC( OC_PRINT ): 2673 case XC( OC_PRINT ):
2667 case XC( OC_PRINTF ): { 2674 case XC( OC_PRINTF ): {
2668 FILE *F = stdout; 2675 FILE *F = stdout;
2676 IF_FEATURE_AWK_GNU_EXTENSIONS(int len;)
2669 2677
2670 if (op->r.n) { 2678 if (op->r.n) {
2671 rstream *rsm = newfile(R.s); 2679 rstream *rsm = newfile(R.s);
@@ -2703,8 +2711,12 @@ static var *evaluate(node *op, var *res)
2703 fputs(getvar_s(intvar[ORS]), F); 2711 fputs(getvar_s(intvar[ORS]), F);
2704 2712
2705 } else { /* OC_PRINTF */ 2713 } else { /* OC_PRINTF */
2706 char *s = awk_printf(op1); 2714 char *s = awk_printf(op1, &len);
2715#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2716 fwrite(s, len, 1, F);
2717#else
2707 fputs(s, F); 2718 fputs(s, F);
2719#endif
2708 free(s); 2720 free(s);
2709 } 2721 }
2710 fflush(F); 2722 fflush(F);
@@ -2978,7 +2990,7 @@ static var *evaluate(node *op, var *res)
2978 break; 2990 break;
2979 2991
2980 case XC( OC_SPRINTF ): 2992 case XC( OC_SPRINTF ):
2981 setvar_p(res, awk_printf(op1)); 2993 setvar_p(res, awk_printf(op1, NULL));
2982 break; 2994 break;
2983 2995
2984 case XC( OC_UNARY ): { 2996 case XC( OC_UNARY ): {
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index 92c83d719..cf9b722dc 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -383,6 +383,11 @@ testing "awk errors on missing delete arg" \
383 "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" "" 383 "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
384SKIP= 384SKIP=
385 385
386optional FEATURE_AWK_GNU_EXTENSIONS
387testing "awk printf('%c') can output NUL" \
388 "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n"
389SKIP=
390
386# testing "description" "command" "result" "infile" "stdin" 391# testing "description" "command" "result" "infile" "stdin"
387testing 'awk negative field access' \ 392testing 'awk negative field access' \
388 'awk 2>&1 -- '\''{ $(-1) }'\' \ 393 'awk 2>&1 -- '\''{ $(-1) }'\' \