[PATCH] awk: allow printf('%c') to output NUL, closes 13486

Denys Vlasenko vda.linux at googlemail.com
Tue Feb 2 12:53:03 UTC 2021


Applied, thanks!

On Wed, Jan 27, 2021 at 12:19 PM Ron Yorston <rmy at pobox.com> wrote:
>
> 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 at pobox.com>
> ---
>  editors/awk.c       | 18 +++++++++++++++---
>  testsuite/awk.tests |  5 +++++
>  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
>  }
>
>  /* formatted output into an allocated buffer, return ptr to buffer */
> -static char *awk_printf(node *n)
> +#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS
> +# define awk_printf(a, b) awk_printf(a)
> +#endif
> +static char *awk_printf(node *n, int *len)
>  {
>         char *b = NULL;
>         char *fmt, *s, *f;
> @@ -2209,6 +2212,10 @@ static char *awk_printf(node *n)
>         nvfree(v);
>         b = xrealloc(b, i + 1);
>         b[i] = '\0';
> +#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
> +       if (len)
> +               *len = i;
> +#endif
>         return b;
>  }
>
> @@ -2666,6 +2673,7 @@ static var *evaluate(node *op, var *res)
>                 case XC( OC_PRINT ):
>                 case XC( OC_PRINTF ): {
>                         FILE *F = stdout;
> +                       IF_FEATURE_AWK_GNU_EXTENSIONS(int len;)
>
>                         if (op->r.n) {
>                                 rstream *rsm = newfile(R.s);
> @@ -2703,8 +2711,12 @@ static var *evaluate(node *op, var *res)
>                                 fputs(getvar_s(intvar[ORS]), F);
>
>                         } else {        /* OC_PRINTF */
> -                               char *s = awk_printf(op1);
> +                               char *s = awk_printf(op1, &len);
> +#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
> +                               fwrite(s, len, 1, F);
> +#else
>                                 fputs(s, F);
> +#endif
>                                 free(s);
>                         }
>                         fflush(F);
> @@ -2978,7 +2990,7 @@ static var *evaluate(node *op, var *res)
>                         break;
>
>                 case XC( OC_SPRINTF ):
> -                       setvar_p(res, awk_printf(op1));
> +                       setvar_p(res, awk_printf(op1, NULL));
>                         break;
>
>                 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" \
>         "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
>  SKIP=
>
> +optional FEATURE_AWK_GNU_EXTENSIONS
> +testing "awk printf('%c') can output NUL" \
> +       "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n"
> +SKIP=
> +
>  # testing "description" "command" "result" "infile" "stdin"
>  testing 'awk negative field access' \
>         'awk 2>&1 -- '\''{ $(-1) }'\' \
> --
> 2.29.2
>
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list