[RFC,v2] Add [v]aprintf(3)
Checks
Commit Message
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)
| ^~~~~~~~~~~~~~~
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
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)
Comments
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)
Hi Adhemerval,
On 2026-03-17T17:16:06-0300, Adhemerval Zanella Netto wrote:
> The below range-diff should fix the issue and export the symbols.
Thanks! I've applied it, and it builds.
> 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.
I think it'd be nice to use it internally in the future (just like
everything, I guess).
>
> There is also the question if we need to nldbl variants for some ABIs
> (I don't recall in details the issue).
I don't know what ldbl and nldbl are, so I can't tell.
> We will need proper documentation,
Yup. We already have a manual page for them; I'll now add the glibc
documentation in the patch. This should be the easy part. :)
> some regressions tests,
I'll try to imitate the vasprintf(3) tests. I found there's
"libio/tst-asprintf-null.c".
> and the
> fortification wrapper.
Okay; I'll try this too.
[...]
> 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;
> + }
I've put vaprintf in libio/Versions.
Cheers,
Alex
On Tue, 17 Mar 2026, Alejandro Colomar wrote:
> > There is also the question if we need to nldbl variants for some ABIs
> > (I don't recall in details the issue).
>
> I don't know what ldbl and nldbl are, so I can't tell.
On platforms with two long double formats (-mlong-double-64 and
-mlong-double-128), all printf-like functions should have two versions,
with __nldbl_* ones for the -mlong-double-64 case (with associated symbol
versions in sysdeps/ieee754/ldbl-opt/Versions and tests enabled through
sysdeps/ieee754/ldbl-opt/Makefile, and libio/bits/stdio-ldbl.h having a
call to an appropriate redirection macro). (There are also wrappers under
the unprefixed names for libnldbl_nonshared.a, which I think is intended
for compilers lacking asm redirection support, and probably doesn't work
very well.)
On powerpc64le, there are three long double formats, so there are also
__*ieee128 versions using binary128 long double, versions in
sysdeps/ieee754/ldbl-128ibm-compat/Versions, tests enabled in
sysdeps/ieee754/ldbl-128ibm-compat/Makefile.
All symbol versions also require corresponding updates to *.abilist. For
simple cases of a function at the same version on all supported platforms,
"make update-all-abi" suffices, but for printf-like functions, platforms
with __nldbl_* need those added to the relevant .abilist files, and
likewise for __*ieee128 on powerpc64le.
The effect is that printf-like functions are some of the hardest to add to
glibc and testing on powerpc64le is essential (and testing with
build-many-glibcs.py may be useful as well to make sure that all supported
ABIs build and pass the compilation parts of the testsuite, but takes a
lot of resources).
> > and the
> > fortification wrapper.
>
> Okay; I'll try this too.
Of course where functions have fortification wrappers, those need all the
same long double variants as well.
Hi Joseph,
On 2026-03-17T20:52:50+0000, Joseph Myers wrote:
> On Tue, 17 Mar 2026, Alejandro Colomar wrote:
>
> > > There is also the question if we need to nldbl variants for some ABIs
> > > (I don't recall in details the issue).
> >
> > I don't know what ldbl and nldbl are, so I can't tell.
>
> On platforms with two long double formats (-mlong-double-64 and
> -mlong-double-128), all printf-like functions should have two versions,
> with __nldbl_* ones for the -mlong-double-64 case (with associated symbol
> versions in sysdeps/ieee754/ldbl-opt/Versions and tests enabled through
> sysdeps/ieee754/ldbl-opt/Makefile, and libio/bits/stdio-ldbl.h having a
> call to an appropriate redirection macro). (There are also wrappers under
> the unprefixed names for libnldbl_nonshared.a, which I think is intended
> for compilers lacking asm redirection support, and probably doesn't work
> very well.)
>
> On powerpc64le, there are three long double formats, so there are also
> __*ieee128 versions using binary128 long double, versions in
> sysdeps/ieee754/ldbl-128ibm-compat/Versions, tests enabled in
> sysdeps/ieee754/ldbl-128ibm-compat/Makefile.
>
> All symbol versions also require corresponding updates to *.abilist. For
> simple cases of a function at the same version on all supported platforms,
> "make update-all-abi" suffices, but for printf-like functions, platforms
> with __nldbl_* need those added to the relevant .abilist files, and
> likewise for __*ieee128 on powerpc64le.
>
> The effect is that printf-like functions are some of the hardest to add to
> glibc
Ouch; indeed. I'll first work on the documentation and basic tests, and
I'll probably need a lot of help after that for this part. Thanks!
Cheers,
Alex
> and testing on powerpc64le is essential (and testing with
> build-many-glibcs.py may be useful as well to make sure that all supported
> ABIs build and pass the compilation parts of the testsuite, but takes a
> lot of resources).
>
> > > and the
> > > fortification wrapper.
> >
> > Okay; I'll try this too.
>
> Of course where functions have fortification wrappers, those need all the
> same long double variants as well.
>
> --
> Joseph S. Myers
> josmyers@redhat.com
>
* Joseph Myers:
> On Tue, 17 Mar 2026, Alejandro Colomar wrote:
>
>> > There is also the question if we need to nldbl variants for some ABIs
>> > (I don't recall in details the issue).
>>
>> I don't know what ldbl and nldbl are, so I can't tell.
>
> On platforms with two long double formats (-mlong-double-64 and
> -mlong-double-128), all printf-like functions should have two versions,
> with __nldbl_* ones for the -mlong-double-64 case (with associated symbol
> versions in sysdeps/ieee754/ldbl-opt/Versions and tests enabled through
> sysdeps/ieee754/ldbl-opt/Makefile, and libio/bits/stdio-ldbl.h having a
> call to an appropriate redirection macro). (There are also wrappers under
> the unprefixed names for libnldbl_nonshared.a, which I think is intended
> for compilers lacking asm redirection support, and probably doesn't work
> very well.)
>
> On powerpc64le, there are three long double formats, so there are also
> __*ieee128 versions using binary128 long double, versions in
> sysdeps/ieee754/ldbl-128ibm-compat/Versions, tests enabled in
> sysdeps/ieee754/ldbl-128ibm-compat/Makefile.
>
> All symbol versions also require corresponding updates to *.abilist. For
> simple cases of a function at the same version on all supported platforms,
> "make update-all-abi" suffices, but for printf-like functions, platforms
> with __nldbl_* need those added to the relevant .abilist files, and
> likewise for __*ieee128 on powerpc64le.
>
> The effect is that printf-like functions are some of the hardest to add to
> glibc and testing on powerpc64le is essential (and testing with
> build-many-glibcs.py may be useful as well to make sure that all supported
> ABIs build and pass the compilation parts of the testsuite, but takes a
> lot of resources).
There's another issue specific to aprintf: I don't think we want it to
fail with EOVERFLOW if the length of the string is longer than INT_MAX.
Fixing that will be quite difficult because the INT_MAX limit is
currently built into the generic vfprintf code.
Thanks,
Florian
Hi Florian,
On 2026-03-18T08:18:30+0100, Florian Weimer wrote:
> There's another issue specific to aprintf: I don't think we want it to
> fail with EOVERFLOW if the length of the string is longer than INT_MAX.
> Fixing that will be quite difficult because the INT_MAX limit is
> currently built into the generic vfprintf code.
I thought about it, and we could initially fail with EOVERFLOW, and then
we could transition to removing it in the future, when we figure out how
to do it.
But I agree, ideally, we shouldn't EOVERFLOW.
Have a lovely day!
Alex
On Wed, 18 Mar 2026, Alejandro Colomar wrote:
> I still need to do the long double variants, as Joseph said. Joseph
> would you mind pointing me to what I should do about it and how?
Pick some existing printf-like function, find all the references to it and
its variants in the source tree and use that as a basis for what needs
adding for any new such function.
Hi Joseph,
On 2026-03-18T18:27:05+0000, Joseph Myers wrote:
> On Wed, 18 Mar 2026, Alejandro Colomar wrote:
>
> > I still need to do the long double variants, as Joseph said. Joseph
> > would you mind pointing me to what I should do about it and how?
>
> Pick some existing printf-like function, find all the references to it and
> its variants in the source tree and use that as a basis for what needs
> adding for any new such function.
Thanks!
In file names, I see:
$ find | grep asprintf | grep -v -e xasprintf -e^./patches/
./sysdeps/ieee754/ldbl-opt/nldbl-asprintf_chk.c
./sysdeps/ieee754/ldbl-opt/nldbl-vasprintf_chk.c
./sysdeps/ieee754/ldbl-opt/nldbl-vasprintf.c
./sysdeps/ieee754/ldbl-opt/nldbl-asprintf.c
./sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vasprintf_chk.c
./sysdeps/ieee754/ldbl-128ibm-compat/ieee128-asprintf.c
./sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vasprintf.c
./sysdeps/ieee754/ldbl-128ibm-compat/ieee128-asprintf_chk.c
./stdio-common/asprintf.c
./debug/asprintf_chk.c
./debug/vasprintf_chk.c
./libio/tst-asprintf-null.c
./libio/vasprintf.c
I already did the libio/ and stdio-common/ part. It seems I still need
debug/ and sysdeps/.
$ find | grep aprintf | grep -v ^./patches/
./stdio-common/aprintf.c
./libio/tst-aprintf.c
./libio/vaprintf.c
What's the difference between ___asprintf_chk() with 3 '_' and
__asprintf_chk() with 2 '_'?
Then, grepping for mentions within code, and ignoring calls, and other
irrelevant stuff, I have a longer list.
$ grep -rl '\b_*asprintf' \
| sort \
| grep -v \
-e^time/ -e^support/ -e^sunrpc/ -e^string/ \
-e^stdio-common/tst- -e^resolv/ -e^posix/tst- \
-e^patches/ -e^nss/ -e^nscd/ -e^nis/ -e^misc/ -e^math/ \
-e^manual/ -e^malloc/ -e^login/ -e^locale/ -e^io/ \
-e^intl/ -e^inet/ -e^iconv/ -e^elf/ -e^dlfcn/ \
-e^dirent/ -e^catgets/ -e^benchtests/ -e^assert/ \
-e^ChangeLog -e^NEWS \
| grep -v \
-e^libio/ -e^stdio-common/ -e^include/
debug/Makefile
debug/Versions
debug/asprintf_chk.c
debug/pcprofiledump.c
debug/tst-fortify.c
sysdeps/ieee754/ldbl-128ibm-compat/Makefile
sysdeps/ieee754/ldbl-128ibm-compat/Versions
sysdeps/ieee754/ldbl-128ibm-compat/ieee128-asprintf.c
sysdeps/ieee754/ldbl-128ibm-compat/ieee128-asprintf_chk.c
sysdeps/ieee754/ldbl-128ibm-compat/test-printf-chk-ldbl-compat.c
sysdeps/ieee754/ldbl-128ibm-compat/test-printf-ldbl-compat.c
sysdeps/ieee754/ldbl-opt/Makefile
sysdeps/ieee754/ldbl-opt/Versions
sysdeps/ieee754/ldbl-opt/nldbl-asprintf.c
sysdeps/ieee754/ldbl-opt/nldbl-asprintf_chk.c
sysdeps/ieee754/ldbl-opt/nldbl-compat.c
sysdeps/ieee754/ldbl-opt/nldbl-compat.h
sysdeps/mach/hurd/execveat.c
sysdeps/mach/hurd/i386/libc.abilist
sysdeps/mach/hurd/spawni.c
sysdeps/mach/hurd/x86_64/libc.abilist
sysdeps/mach/strerror_l.c
sysdeps/unix/sysv/linux/aarch64/libc.abilist
sysdeps/unix/sysv/linux/alpha/libc.abilist
sysdeps/unix/sysv/linux/arc/libc.abilist
sysdeps/unix/sysv/linux/arm/be/libc.abilist
sysdeps/unix/sysv/linux/arm/le/libc.abilist
sysdeps/unix/sysv/linux/csky/libc.abilist
sysdeps/unix/sysv/linux/hppa/libc.abilist
sysdeps/unix/sysv/linux/i386/libc.abilist
sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
sysdeps/unix/sysv/linux/or1k/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
sysdeps/unix/sysv/linux/sh/be/libc.abilist
sysdeps/unix/sysv/linux/sh/le/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
Of this, list, is it all necessary? And is it all manually updated?
Or is part of it automated? And if so, which part should I ignore?
Have a lovely night!
Alex
@@ -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 \
@@ -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
new file mode 100644
@@ -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)
@@ -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 \
new file mode 100644
@@ -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)