[RFC v2] Add [v]aprintf(3)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Mar 17 20:16:06 GMT 2026



On 17/03/26 16:26, Alejandro Colomar wrote:
> Signed-off-by: Alejandro Colomar <alx@kernel.org>
> ---
> 
> Hi!
> 
> I've figured out how to add these to the Makefiles.  I'm now having
> issues with the aliases, which I don't understand at all.  I more or
> less imitated how [v]asprintf(3) are implemented, but obviously did
> something wrong.
> 
> Would you mind helping with this error?
> 
> 	In file included from <command-line>:
> 	./../include/libc-symbols.h:474:33: error: ‘__EI_aprintf’ aliased to undefined symbol ‘__GI_aprintf’
> 	  474 |   extern thread __typeof (name) __EI_##name \
> 	      |                                 ^~~~~
> 	./../include/libc-symbols.h:470:3: note: in expansion of macro ‘__hidden_ver2’
> 	  470 |   __hidden_ver2 (, local, internal, name)
> 	      |   ^~~~~~~~~~~~~
> 	./../include/libc-symbols.h:478:41: note: in expansion of macro ‘__hidden_ver1’
> 	  478 | #  define hidden_def(name)              __hidden_ver1(__GI_##name, name, name);
> 	      |                                         ^~~~~~~~~~~~~
> 	./../include/libc-symbols.h:559:32: note: in expansion of macro ‘hidden_def’
> 	  559 | # define libc_hidden_def(name) hidden_def (name)
> 	      |                                ^~~~~~~~~~
> 	../sysdeps/generic/math_ldbl_opt.h:13:38: note: in expansion of macro ‘libc_hidden_def’
> 	   13 | #define ldbl_hidden_def(local, name) libc_hidden_def (name)
> 	      |                                      ^~~~~~~~~~~~~~~
> 	aprintf.c:37:1: note: in expansion of macro ‘ldbl_hidden_def’
> 	   37 | ldbl_hidden_def (__aprintf, aprintf)
> 	      | ^~~~~~~~~~~~~~~

The below range-diff should fix the issue and export the symbols.  Any
*hidden_def should be paired with *hidden_proto, otherwise you get
these crypt messages.

Also, the hidden proto/def is only required iff you intend to use the
symbol internall on glibc and also export it as a public symbol (so
the internal usage is binding to the internal symbol like -Bsymbolic).
Otherwise if you just want to export it there is no need of it.

There is also the question if we need to nldbl variants for some ABIs
(I don't recall in details the issue).

We will need proper documentation, some regressions tests, and the
fortification wrapper.

diff --git a/include/stdio.h b/include/stdio.h
index 88166993dd..cb9b9210be 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -241,6 +241,9 @@ extern const char *__get_errname (int) attribute_hidden;

 libc_hidden_ldbl_proto (__asprintf)

+extern __typeof (aprintf) __aprintf;
+libc_hidden_ldbl_proto (__aprintf)
+
 #  if IS_IN (libc)
 extern FILE *_IO_new_fopen (const char*, const char*);
 #   define fopen(fname, mode) _IO_new_fopen (fname, mode)
diff --git a/stdio-common/Versions b/stdio-common/Versions
index 8e1cbf8559..ab1713f978 100644
--- a/stdio-common/Versions
+++ b/stdio-common/Versions
@@ -71,6 +71,9 @@ libc {
     __isoc23_sscanf;
     __isoc23_vsscanf;
   }
+  GLIBC_2.44 {
+    aprintf; vaprintf;
+  }
   GLIBC_PRIVATE {
     # global variables
     _itoa_lower_digits;
diff --git a/stdio-common/aprintf.c b/stdio-common/aprintf.c
index f2d0dbb27b..bee4966707 100644
--- a/stdio-common/aprintf.c
+++ b/stdio-common/aprintf.c
@@ -34,7 +34,7 @@ ___aprintf (const char *fmt, ...)

   return p;
 }
-ldbl_hidden_def (__aprintf, aprintf)
+ldbl_hidden_def (___aprintf, __aprintf)

 ldbl_strong_alias (___aprintf, __aprintf)
 ldbl_weak_alias (___aprintf, aprintf)

> 
> Cheers,
> Alex
> 
>  libio/Makefile         |  3 ++-
>  libio/stdio.h          |  8 ++++++++
>  libio/vaprintf.c       | 39 +++++++++++++++++++++++++++++++++++++++
>  stdio-common/Makefile  |  2 ++
>  stdio-common/aprintf.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 91 insertions(+), 1 deletion(-)
>  create mode 100644 libio/vaprintf.c
>  create mode 100644 stdio-common/aprintf.c
> 
> diff --git a/libio/Makefile b/libio/Makefile
> index 08e1e0ec..acb578db 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -43,7 +43,7 @@ routines	:=							      \
>  									      \
>  	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
>  	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
> -	iovdprintf vscanf vsnprintf obprintf fcloseall fseeko ftello	      \
> +	vaprintf iovdprintf vscanf vsnprintf obprintf fcloseall fseeko ftello \
>  	freopen64 fseeko64 ftello64					      \
>  									      \
>  	__fbufsize __freading __fwriting __freadable __fwritable __flbf	      \
> @@ -63,6 +63,7 @@ routines_no_fortify += \
>    iovdprintf \
>    swprintf \
>    vasprintf \
> +  vaprintf \
>    vsnprintf \
>    vswprintf \
>    vwprintf \
> diff --git a/libio/stdio.h b/libio/stdio.h
> index 3bf6a1f6..3db363f1 100644
> --- a/libio/stdio.h
> +++ b/libio/stdio.h
> @@ -410,6 +410,14 @@ extern int __asprintf (char **__restrict __ptr,
>  extern int asprintf (char **__restrict __ptr,
>  		     const char *__restrict __fmt, ...)
>       __THROWNL __attribute__ ((__format__ (__printf__, 2, 3))) __wur;
> +
> +/* Write formatted output to a string dynamically allocated with `malloc'.  */
> +extern char *vaprintf (const char *__restrict __f, __gnuc_va_list __arg)
> +     __THROWNL __attribute__ ((__format__ (__printf__, 1, 0)))
> +     __attribute_malloc__;
> +extern char *aprintf (const char *__restrict __fmt, ...)
> +     __THROWNL __attribute__ ((__format__ (__printf__, 1, 2)))
> +     __attribute_malloc__;
>  #endif
>  
>  #ifdef __USE_XOPEN2K8
> diff --git a/libio/vaprintf.c b/libio/vaprintf.c
> new file mode 100644
> index 00000000..6789052f
> --- /dev/null
> +++ b/libio/vaprintf.c
> @@ -0,0 +1,39 @@
> +/* Copyright (C) 2026 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.
> +
> +   As a special exception, if you link the code in this file with
> +   files compiled with a GNU compiler to produce an executable,
> +   that does not cause the resulting executable to be covered by
> +   the GNU Lesser General Public License.  This exception does not
> +   however invalidate any other reasons why the executable file
> +   might be covered by the GNU Lesser General Public License.
> +   This exception applies to code released by its copyright holders
> +   in files containing the exception.  */
> +
> +#include <libioP.h>
> +#include <stdarg.h>
> +#include <stddef.h>
> +#include <stdio.h>
> +
> +char *
> +__vaprintf (const char *fmt, va_list args)
> +{
> +  char *p;
> +
> +  return __vasprintf_internal (&p, fmt, args, 0) < 0 ? NULL : p;
> +}
> +ldbl_weak_alias (__vaprintf, vaprintf)
> diff --git a/stdio-common/Makefile b/stdio-common/Makefile
> index 21094483..ec52c1ea 100644
> --- a/stdio-common/Makefile
> +++ b/stdio-common/Makefile
> @@ -90,6 +90,7 @@ routines := \
>    _itoa \
>    _itowa \
>    asprintf \
> +  aprintf \
>    ctermid \
>    cuserid \
>    dprintf \
> @@ -178,6 +179,7 @@ routines := \
>  # Exclude fortified routines from being built with _FORTIFY_SOURCE
>  routines_no_fortify += \
>    asprintf \
> +  aprintf \
>    dprintf \
>    fprintf \
>    printf \
> diff --git a/stdio-common/aprintf.c b/stdio-common/aprintf.c
> new file mode 100644
> index 00000000..f2d0dbb2
> --- /dev/null
> +++ b/stdio-common/aprintf.c
> @@ -0,0 +1,40 @@
> +/* Copyright (C) 2026 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <stdarg.h>
> +#include <libioP.h>
> +
> +/* Write formatted output from FORMAT to a string which is
> +   allocated with malloc.  */
> +/* VARARGS1 */
> +char *
> +___aprintf (const char *fmt, ...)
> +{
> +  char *p;
> +  va_list ap;
> +
> +  va_start (ap, fmt);
> +  if (__vasprintf_internal (&p, fmt, ap, 0) < 0)
> +    p = NULL;
> +  va_end (ap);
> +
> +  return p;
> +}
> +ldbl_hidden_def (__aprintf, aprintf)
> +
> +ldbl_strong_alias (___aprintf, __aprintf)
> +ldbl_weak_alias (___aprintf, aprintf)
> 
> Range-diff against v1:
> 1:  e5defcbd ! 1:  916855e5 libio/: Add [v]aprintf()
>     @@ Metadata
>      Author: Alejandro Colomar <alx@kernel.org>
>      
>       ## Commit message ##
>     -    libio/: Add [v]aprintf()
>     +    Add [v]aprintf(3)
>      
>          Signed-off-by: Alejandro Colomar <alx@kernel.org>
>      
>     + ## libio/Makefile ##
>     +@@ libio/Makefile: routines	:=							      \
>     + 									      \
>     + 	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
>     + 	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
>     +-	iovdprintf vscanf vsnprintf obprintf fcloseall fseeko ftello	      \
>     ++	vaprintf iovdprintf vscanf vsnprintf obprintf fcloseall fseeko ftello \
>     + 	freopen64 fseeko64 ftello64					      \
>     + 									      \
>     + 	__fbufsize __freading __fwriting __freadable __fwritable __flbf	      \
>     +@@ libio/Makefile: routines_no_fortify += \
>     +   iovdprintf \
>     +   swprintf \
>     +   vasprintf \
>     ++  vaprintf \
>     +   vsnprintf \
>     +   vswprintf \
>     +   vwprintf \
>     +
>       ## libio/stdio.h ##
>      @@ libio/stdio.h: extern int __asprintf (char **__restrict __ptr,
>       extern int asprintf (char **__restrict __ptr,
>     @@ libio/vaprintf.c (new)
>      +   This exception applies to code released by its copyright holders
>      +   in files containing the exception.  */
>      +
>     -+#include "libioP.h"
>     ++#include <libioP.h>
>      +#include <stdarg.h>
>      +#include <stddef.h>
>      +#include <stdio.h>
>      +
>     -+char **
>     ++char *
>      +__vaprintf (const char *fmt, va_list args)
>      +{
>      +  char *p;
>      +
>     -+  return (__vasprintf_internal (&p, fmt, args, 0) < 0 ? NULL : p;
>     ++  return __vasprintf_internal (&p, fmt, args, 0) < 0 ? NULL : p;
>      +}
>      +ldbl_weak_alias (__vaprintf, vaprintf)
>     +
>     + ## stdio-common/Makefile ##
>     +@@ stdio-common/Makefile: routines := \
>     +   _itoa \
>     +   _itowa \
>     +   asprintf \
>     ++  aprintf \
>     +   ctermid \
>     +   cuserid \
>     +   dprintf \
>     +@@ stdio-common/Makefile: routines := \
>     + # Exclude fortified routines from being built with _FORTIFY_SOURCE
>     + routines_no_fortify += \
>     +   asprintf \
>     ++  aprintf \
>     +   dprintf \
>     +   fprintf \
>     +   printf \
>     +
>     + ## stdio-common/aprintf.c (new) ##
>     +@@
>     ++/* Copyright (C) 2026 Free Software Foundation, Inc.
>     ++   This file is part of the GNU C Library.
>      +
>     -+char **
>     -+__aprintf (const char *fmt, ...)
>     ++   The GNU C Library is free software; you can redistribute it and/or
>     ++   modify it under the terms of the GNU Lesser General Public
>     ++   License as published by the Free Software Foundation; either
>     ++   version 2.1 of the License, or (at your option) any later version.
>     ++
>     ++   The GNU C Library is distributed in the hope that it will be useful,
>     ++   but WITHOUT ANY WARRANTY; without even the implied warranty of
>     ++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>     ++   Lesser General Public License for more details.
>     ++
>     ++   You should have received a copy of the GNU Lesser General Public
>     ++   License along with the GNU C Library; if not, see
>     ++   <https://www.gnu.org/licenses/>.  */
>     ++
>     ++#include <stdarg.h>
>     ++#include <libioP.h>
>     ++
>     ++/* Write formatted output from FORMAT to a string which is
>     ++   allocated with malloc.  */
>     ++/* VARARGS1 */
>     ++char *
>     ++___aprintf (const char *fmt, ...)
>      +{
>      +  char *p;
>      +  va_list ap;
>      +
>     -+  va_start(ap, fmt);
>     -+  p = __vaprintf(fmt, ap);
>     -+  va_end(ap);
>     ++  va_start (ap, fmt);
>     ++  if (__vasprintf_internal (&p, fmt, ap, 0) < 0)
>     ++    p = NULL;
>     ++  va_end (ap);
>      +
>      +  return p;
>      +}
>     -+ldbl_weak_alias (__aprintf, aprintf)
>     ++ldbl_hidden_def (__aprintf, aprintf)
>     ++
>     ++ldbl_strong_alias (___aprintf, __aprintf)
>     ++ldbl_weak_alias (___aprintf, aprintf)



More information about the Libc-alpha mailing list