[RFC,v8,0/3] Add [v]aprintf(3)

Message ID cover.1781209440.git.alx@kernel.org (mailing list archive)
Headers
Series Add [v]aprintf(3) |

Message

Alejandro Colomar June 11, 2026, 8:38 p.m. UTC
  Hi!

Changes in v8:

-  Rebase.  In trunk, patch v7 3/3 has already been applied.
-  Amended with changes agreed with Adhemerval in v7:
   -  Add tests to "debug/tst-fortify.c".
   -  Use __attr_dealloc_free.
   -  Remove #if 0 in "libio/tst-aprintf.c".
   -  Handle ENOMEM in "libio/tst-aprintf.c".
   -  Fix return type in "sysdeps/ieee754/ldbl-opt/nldbl-compat.c".
   -  s/GLIBC_2_4_4/GLIBC_2_44/
   -  I've removed some stuff in commit 1/1, and then I've removed some
      other stuff, but I was less sure of what I was doing, so I put
      that in a separate commit (2/3).  Adhemerval, would you mind
      revising whether what I did is correct, and whether there's more
      stuff I should remove?  I'd appreciate a diff that applies on top
      of this patch, because I'm a bit lost with all these definitions.

I've done 'make' and 'make test', which passes, but I suspect on other
archs this might be broken.  I've downgraded this to just RFC.


Have a lovely night!
Alex


Alejandro Colomar (3):
  Add [v]aprintf(3)
  try.reducing.symbols
  manual/: Prefer aprintf(3) over asprintf(3)

 debug/Makefile                                |  4 ++
 debug/Versions                                |  3 +
 debug/aprintf_chk.c                           | 51 ++++++++++++++
 debug/tst-fortify.c                           | 14 ++++
 debug/vaprintf_chk.c                          | 39 +++++++++++
 include/stdio.h                               |  7 ++
 libio/Makefile                                |  4 +-
 libio/Versions                                |  3 +
 libio/bits/stdio-ldbl.h                       |  5 ++
 libio/bits/stdio2-decl.h                      |  8 +++
 libio/bits/stdio2.h                           | 24 +++++++
 libio/stdio.h                                 | 10 +++
 libio/tst-aprintf.c                           | 68 +++++++++++++++++++
 libio/vaprintf.c                              | 38 +++++++++++
 manual/examples/rprintf.c                     |  4 +-
 manual/stdio.texi                             | 30 +++++++-
 manual/string.texi                            |  2 +-
 stdio-common/Makefile                         |  2 +
 stdio-common/Versions                         |  3 +
 stdio-common/aprintf.c                        | 37 ++++++++++
 sysdeps/ieee754/ldbl-128ibm-compat/Makefile   |  8 ++-
 sysdeps/ieee754/ldbl-128ibm-compat/Versions   |  6 ++
 .../ldbl-128ibm-compat/ieee128-aprintf.c      | 36 ++++++++++
 .../ldbl-128ibm-compat/ieee128-aprintf_chk.c  | 40 +++++++++++
 .../ldbl-128ibm-compat/ieee128-vaprintf.c     | 29 ++++++++
 .../ldbl-128ibm-compat/ieee128-vaprintf_chk.c | 31 +++++++++
 .../test-printf-chk-ldbl-compat.c             | 31 ++++++++-
 .../test-printf-ldbl-compat.c                 | 31 ++++++++-
 sysdeps/ieee754/ldbl-opt/Makefile             |  6 ++
 sysdeps/ieee754/ldbl-opt/Versions             |  8 +++
 sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c      | 14 ++++
 sysdeps/ieee754/ldbl-opt/nldbl-aprintf_chk.c  | 15 ++++
 sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c     |  9 +++
 sysdeps/ieee754/ldbl-opt/nldbl-vaprintf_chk.c |  8 +++
 sysdeps/mach/hurd/i386/libc.abilist           |  4 ++
 sysdeps/mach/hurd/x86_64/libc.abilist         |  4 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  4 ++
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  4 ++
 sysdeps/unix/sysv/linux/arc/libc.abilist      |  4 ++
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |  4 ++
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  4 ++
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  4 ++
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  4 ++
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  4 ++
 .../sysv/linux/loongarch/lp64/libc.abilist    |  4 ++
 .../sysv/linux/m68k/coldfire/libc.abilist     |  4 ++
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  4 ++
 .../sysv/linux/microblaze/be/libc.abilist     |  4 ++
 .../sysv/linux/microblaze/le/libc.abilist     |  4 ++
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  4 ++
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |  4 ++
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  4 ++
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  4 ++
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |  4 ++
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  4 ++
 .../powerpc/powerpc32/nofpu/libc.abilist      |  4 ++
 .../linux/powerpc/powerpc64/be/libc.abilist   |  4 ++
 .../linux/powerpc/powerpc64/le/libc.abilist   |  4 ++
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |  4 ++
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  4 ++
 sysdeps/unix/sysv/linux/s390/libc.abilist     |  4 ++
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |  4 ++
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  4 ++
 .../sysv/linux/sparc/sparc32/libc.abilist     |  4 ++
 .../sysv/linux/sparc/sparc64/libc.abilist     |  4 ++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  4 ++
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  4 ++
 67 files changed, 749 insertions(+), 11 deletions(-)
 create mode 100644 debug/aprintf_chk.c
 create mode 100644 debug/vaprintf_chk.c
 create mode 100644 libio/tst-aprintf.c
 create mode 100644 libio/vaprintf.c
 create mode 100644 stdio-common/aprintf.c
 create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf.c
 create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf_chk.c
 create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf.c
 create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf_chk.c
 create mode 100644 sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c
 create mode 100644 sysdeps/ieee754/ldbl-opt/nldbl-aprintf_chk.c
 create mode 100644 sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c
 create mode 100644 sysdeps/ieee754/ldbl-opt/nldbl-vaprintf_chk.c

Range-diff against v7:
1:  f78192ebc9ce ! 1:  e5212bcc6f2c Add [v]aprintf(3)
    @@ debug/aprintf_chk.c (new)
     +libc_hidden_def (__aprintf_chk)
     +#endif
     
    + ## debug/tst-fortify.c ##
    +@@ debug/tst-fortify.c: do_test (void)
    +     free (my_ptr);
    +   CHK_FAIL2_END
    + 
    ++  CHK_FAIL2_START
    ++  my_ptr = aprintf (buf2, str4, &n1, str5, &n1);
    ++  if (my_ptr == NULL)
    ++    FAIL ();
    ++  else
    ++    free (my_ptr);
    ++  CHK_FAIL2_END
    ++
    +   struct obstack obs;
    +   obstack_init (&obs);
    +   CHK_FAIL2_START
    +@@ debug/tst-fortify.c: do_test (void)
    +   else
    +     free (my_ptr);
    + 
    ++  my_ptr = aprintf ("%s%n%s%n", str4, &n1, str5, &n1);
    ++  if (my_ptr == NULL)
    ++    FAIL ();
    ++  else
    ++    free (my_ptr);
    ++
    +   obstack_init (&obs);
    +   if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14)
    +     FAIL ();
    +
      ## debug/vaprintf_chk.c (new) ##
     @@
     +/* Copyright (C) 2026 Free Software Foundation, Inc.
    @@ include/stdio.h: extern int __vfprintf_chk (FILE *, int, const char *, __gnuc_va
      extern char *__fgets_unlocked_chk (char *buf, size_t size, int n, FILE *fp);
      extern char *__fgets_chk (char *buf, size_t size, int n, FILE *fp);
     +extern char *__aprintf_chk (int, const char *, ...)
    -+     __THROW __attribute_malloc__;
    ++     __THROW __attribute_malloc__ __attr_dealloc_free;
     +extern char *__vaprintf_chk (int, const char *, __gnuc_va_list)
    -+     __THROW __attribute_malloc__;
    ++     __THROW __attribute_malloc__ __attr_dealloc_free;
     +stdio_hidden_ldbl_proto (__, vaprintf_chk)
      extern int __asprintf_chk (char **, int, const char *, ...) __THROW;
      extern int __vasprintf_chk (char **, int, const char *, __gnuc_va_list) __THROW;
    @@ libio/bits/stdio2-decl.h: extern int __vdprintf_chk (int __fd, int __flag,
     +extern char *__aprintf_chk (int __flag,
     +			   const char *__restrict __fmt, ...)
     +     __THROW __attribute__ ((__format__ (__printf__, 2, 3)))
    -+     __attribute_malloc__;
    ++     __attribute_malloc__ __attr_dealloc_free;
     +extern char *__vaprintf_chk (int __flag,
     +			    const char *__restrict __fmt, __gnuc_va_list __ap)
     +     __THROW __attribute__ ((__format__ (__printf__, 2, 0)))
    -+     __attribute_malloc__;
    ++     __attribute_malloc__ __attr_dealloc_free;
      extern int __asprintf_chk (char **__restrict __ptr, int __flag,
      			   const char *__restrict __fmt, ...)
           __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
    @@ libio/stdio.h: extern int asprintf (char **__restrict __ptr,
     +/* Write formatted output to a string dynamically allocated with `malloc'.  */
     +extern char *vaprintf (const char *__restrict __fmt, __gnuc_va_list __ap)
     +     __THROWNL __attribute__ ((__format__ (__printf__, 1, 0)))
    -+     __attribute_malloc__;
    ++     __attribute_malloc__ __attr_dealloc_free;
     +extern char *__aprintf (const char *__restrict __fmt, ...)
     +     __THROWNL __attribute__ ((__format__ (__printf__, 1, 2)))
    -+     __attribute_malloc__;
    ++     __attribute_malloc__ __attr_dealloc_free;
     +extern char *aprintf (const char *__restrict __fmt, ...)
     +     __THROWNL __attribute__ ((__format__ (__printf__, 1, 2)))
    -+     __attribute_malloc__;
    ++     __attribute_malloc__ __attr_dealloc_free;
     +#endif
     +
      #ifdef __USE_XOPEN2K8
    @@ libio/tst-aprintf.c (new)
     +    DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow=");
     +    buf = aprintf ("%2000000000d %2000000000d", 1, 2);
     +    DIAG_POP_NEEDS_COMMENT;
    -+#if 0
    -+    if (buf == NULL)
    -+      TEST_VERIFY (errno == ENOMEM);
    -+#else
     +    /* We should eventually not fail with EOVERFLOW from aprintf.  When
    -+       that happens, this test will fail.  Just remove it and enable the
    -+       test under '#if 0'.  */
    ++       that happens, this test will fail.  */
     +    TEST_VERIFY (buf == NULL);
    -+    TEST_VERIFY (errno == EOVERFLOW);
    -+#endif
    ++    if (errno != ENOMEM)
    ++      TEST_VERIFY (errno == EOVERFLOW);
     +  }
     +
     +  /* Force ENOMEM in the test below.  */
    @@ sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c: static void
     +  buffer = NULL;
        res = __asprintf_chk (&buffer, 1, format, ld, d);
        if (res == -1)
    -     printf ("Error using vasprintf\n");
    +     printf ("Error using asprintf\n");
     @@ sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c: do_test (void)
      
        /* Compare against the expected output.  */
    @@ sysdeps/ieee754/ldbl-opt/nldbl-compat.c: libc_hidden_proto (__nldbl___isoc23_vfw
         we don't need to split this into one file per function for the
         sake of statically linked programs.  */
      
    -+int
    ++char *
     +attribute_compat_text_section
     +__nldbl___aprintf (const char *fmt, ...)
     +{
    @@ sysdeps/ieee754/ldbl-opt/nldbl-compat.c: compat_symbol (libc, __nldbl___fprintf_
      compat_symbol (libc, __nldbl___vprintf_chk, __vprintf_chk, GLIBC_2_3_4);
      compat_symbol (libc, __nldbl___vfprintf_chk, __vfprintf_chk, GLIBC_2_3_4);
      #endif
    -+#if LONG_DOUBLE_COMPAT(libc, GLIBC_2_4_4)
    -+compat_symbol (libc, __nldbl_aprintf, aprintf, GLIBC_2_4_4);
    -+compat_symbol (libc, __nldbl_vaprintf, vaprintf, GLIBC_2_4_4);
    -+compat_symbol (libc, __nldbl___aprintf, __aprintf, GLIBC_2_4_4);
    ++#if LONG_DOUBLE_COMPAT(libc, GLIBC_2_44)
    ++compat_symbol (libc, __nldbl_aprintf, aprintf, GLIBC_2_44);
    ++compat_symbol (libc, __nldbl_vaprintf, vaprintf, GLIBC_2_44);
    ++compat_symbol (libc, __nldbl___aprintf, __aprintf, GLIBC_2_44);
     +#endif
     
    - ## sysdeps/ieee754/ldbl-opt/nldbl-compat.h ##
    -@@ sysdeps/ieee754/ldbl-opt/nldbl-compat.h: NLDBL_DECL (_IO_vfscanf);
    - NLDBL_DECL (vfscanf);
    - NLDBL_DECL (vfwscanf);
    - NLDBL_DECL (obstack_vprintf);
    -+NLDBL_DECL (vaprintf);
    - NLDBL_DECL (vasprintf);
    - NLDBL_DECL (dprintf);
    - NLDBL_DECL (vdprintf);
    -@@ sysdeps/ieee754/ldbl-opt/nldbl-compat.h: NLDBL_DECL (vsprintf);
    - NLDBL_DECL (vsscanf);
    - NLDBL_DECL (vswprintf);
    - NLDBL_DECL (vswscanf);
    -+NLDBL_DECL (__aprintf);
    -+NLDBL_DECL (aprintf);
    - NLDBL_DECL (__asprintf);
    - NLDBL_DECL (asprintf);
    - NLDBL_DECL (__printf_fp);
    -@@ sysdeps/ieee754/ldbl-opt/nldbl-compat.h: extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t,
    - extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t,
    - 				    const wchar_t *__restrict, __gnuc_va_list)
    -   __THROW;
    -+extern char *__nldbl___vaprintf_chk (int, const char *, __gnuc_va_list)
    -+  __THROW __attribute_malloc__;
    - extern int __nldbl___vasprintf_chk (char **, int, const char *, __gnuc_va_list)
    -   __THROW;
    - extern int __nldbl___vdprintf_chk (int, int, const char *, __gnuc_va_list);
    -
      ## sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c (new) ##
     @@
     +#include "nldbl-compat.h"
-:  ------------ > 2:  2ee82e3c0873 try.reducing.symbols
2:  734b3283b946 = 3:  7edeb5ed8e82 manual/: Prefer aprintf(3) over asprintf(3)
3:  22c4ae3f7e5a < -:  ------------ sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c: Fix typo

base-commit: 9da7ad6d74700811c9b4c82b5f5eb555e39241a7
  

Comments

Alejandro Colomar June 25, 2026, 9:44 p.m. UTC | #1
Hi Adhemerval,

On 2026-06-11T22:38:44+0200, Alejandro Colomar wrote:
> Hi!
> 
> Changes in v8:
> 
> -  Rebase.  In trunk, patch v7 3/3 has already been applied.
> -  Amended with changes agreed with Adhemerval in v7:
>    -  Add tests to "debug/tst-fortify.c".
>    -  Use __attr_dealloc_free.
>    -  Remove #if 0 in "libio/tst-aprintf.c".
>    -  Handle ENOMEM in "libio/tst-aprintf.c".
>    -  Fix return type in "sysdeps/ieee754/ldbl-opt/nldbl-compat.c".
>    -  s/GLIBC_2_4_4/GLIBC_2_44/
>    -  I've removed some stuff in commit 1/1, and then I've removed some
>       other stuff, but I was less sure of what I was doing, so I put
>       that in a separate commit (2/3).  Adhemerval, would you mind
>       revising whether what I did is correct, and whether there's more
>       stuff I should remove?  I'd appreciate a diff that applies on top
>       of this patch, because I'm a bit lost with all these definitions.
> 
> I've done 'make' and 'make test', which passes, but I suspect on other
> archs this might be broken.  I've downgraded this to just RFC.

Would you mind having a look at this revision when you have some time?
Thanks!  :)


Have a lovely night!
Alex