[RFC v8 0/3] Add [v]aprintf(3)
Alejandro Colomar
alx@kernel.org
Thu Jun 11 20:38:44 GMT 2026
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
--
2.53.0
More information about the Libc-alpha
mailing list