@@ -71,6 +71,9 @@ libc {
GLIBC_2.43 {
__memset_explicit_chk;
}
+ GLIBC_2.44 {
+ __aprintf_chk; __vaprintf_chk;
+ }
GLIBC_PRIVATE {
__fortify_fail;
}
@@ -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)
@@ -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 \
@@ -90,6 +91,7 @@ tests = \
test-fputs-unbuffered-full \
test-fputws-unbuffered-full \
tst-asprintf-null \
+ tst-aprintf \
tst-atime \
tst-bz22415 \
tst-bz24051 \
@@ -155,6 +155,9 @@ libc {
# f*
fmemopen;
}
+ GLIBC_2.44 {
+ vaprintf;
+ }
GLIBC_PRIVATE {
# Used by NPTL and librt
__libc_fatal;
@@ -125,6 +125,8 @@ __LDBL_REDIR2_DECL (vdprintf_chk)
# ifdef __USE_GNU
__LDBL_REDIR2_DECL (asprintf_chk)
__LDBL_REDIR2_DECL (vasprintf_chk)
+__LDBL_REDIR2_DECL (aprintf_chk)
+__LDBL_REDIR2_DECL (vaprintf_chk)
__LDBL_REDIR2_DECL (obstack_printf_chk)
__LDBL_REDIR2_DECL (obstack_vprintf_chk)
# endif
@@ -72,6 +72,14 @@ extern int __asprintf_chk (char **__restrict __ptr, int __flag,
extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
const char *__restrict __fmt, __gnuc_va_list __arg)
__THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
+extern char *__aprintf_chk (int __flag,
+ const char *__restrict __fmt, ...)
+ __THROW __attribute__ ((__format__ (__printf__, 2, 3)))
+ __attribute_malloc__;
+extern char *__vaprintf_chk (int __flag,
+ const char *__restrict __fmt, __gnuc_va_list __arg)
+ __THROW __attribute__ ((__format__ (__printf__, 2, 0)))
+ __attribute_malloc__;
extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
int __flag, const char *__restrict __format,
...)
@@ -215,6 +215,18 @@ __NTH (__asprintf (char **__restrict __ptr, const char *__restrict __fmt,
__va_arg_pack ());
}
+__fortify_function char *
+__NTH (aprintf (const char *__restrict __fmt, ...))
+{
+ return __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
+}
+
+__fortify_function char *
+__NTH (__aprintf (const char *__restrict __fmt, ...))
+{
+ return __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
+}
+
__fortify_function int
__NTH (obstack_printf (struct obstack *__restrict __obstack,
const char *__restrict __fmt, ...))
@@ -247,6 +259,26 @@ __NTH (__asprintf (__fortify_clang_overload_arg (char **, __restrict, __ptr),
return __r;
}
+__fortify_function char *
+__NTH (aprintf (const char *__restrict __fmt, ...))
+{
+ __gnuc_va_list __fortify_ap;
+ __builtin_va_start (__fortify_ap, __fmt);
+ char * __p = __vaprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __fortify_ap);
+ __builtin_va_end (__fortify_ap);
+ return __p;
+}
+
+__fortify_function char *
+__NTH (__aprintf (const char *__restrict __fmt, ...))
+{
+ __gnuc_va_list __fortify_ap;
+ __builtin_va_start (__fortify_ap, __fmt);
+ char *__p = __vaprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __fortify_ap);
+ __builtin_va_end (__fortify_ap);
+ return __p;
+}
+
__fortify_function_error_function __attribute_overloadable__ int
__NTH (obstack_printf (__fortify_clang_overload_arg (struct obstack *,
__restrict, __obstack),
@@ -264,6 +296,10 @@ __NTH (obstack_printf (__fortify_clang_overload_arg (struct obstack *,
__asprintf_chk (ptr, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
# define __asprintf(ptr, ...) \
__asprintf_chk (ptr, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
+# define aprintf(...) \
+ __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
+# define __aprintf(...) \
+ __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
# define obstack_printf(obstack, ...) \
__obstack_printf_chk (obstack, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
# endif
@@ -275,6 +311,12 @@ __NTH (vasprintf (char **__restrict __ptr, const char *__restrict __fmt,
return __vasprintf_chk (__ptr, __USE_FORTIFY_LEVEL - 1, __fmt, __ap);
}
+__fortify_function char *
+__NTH (vaprintf (const char *__restrict __fmt, __gnuc_va_list __ap))
+{
+ return __vaprintf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __ap);
+}
+
__fortify_function int
__NTH (obstack_vprintf (struct obstack *__restrict __obstack,
const char *__restrict __fmt, __gnuc_va_list __ap))
@@ -412,6 +412,16 @@ extern int asprintf (char **__restrict __ptr,
__THROWNL __attribute__ ((__format__ (__printf__, 2, 3))) __wur;
#endif
+#ifdef __USE_GNU
+/* 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
/* Write formatted output to a file descriptor. */
extern int vdprintf (int __fd, const char *__restrict __fmt,
new file mode 100644
@@ -0,0 +1,56 @@
+/* Test aprintf.
+ 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 <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <sys/resource.h>
+
+static int
+do_test (void)
+{
+ char *buf;
+ {
+ /* Avoid -Wformat-overflow warning. */
+ const char *volatile format = "%2000000000d %2000000000d";
+ buf = aprintf (format, 1, 2);
+ TEST_VERIFY (buf == NULL);
+ }
+ if (errno != ENOMEM)
+ TEST_COMPARE (errno, EOVERFLOW);
+
+ /* Force ENOMEM in the test below. */
+ struct rlimit rl;
+ TEST_COMPARE (getrlimit (RLIMIT_AS, &rl), 0);
+ rl.rlim_cur = 10 * 1024 * 1024;
+ TEST_COMPARE (setrlimit (RLIMIT_AS, &rl), 0);
+
+ buf = aprintf ("%20000000d", 1);
+ TEST_VERIFY (buf == NULL);
+ TEST_COMPARE (errno, ENOMEM);
+
+ /* Success */
+ buf = aprintf ("foo %d", 42);
+ TEST_COMPARE_STRING (buf, "foo 42");
+ free(buf);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
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)
@@ -2578,6 +2578,32 @@ other systems offer this function as an async-signal-safe alternative to
The functions in this section do formatted output and place the results
in dynamically allocated memory.
+@deftypefun {char *} aprintf (const char *@var{template}, @dots{})
+@standards{GNU, stdio.h}
+@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+This function is similar to @code{sprintf},
+except that it dynamically allocates a string
+(as with @code{malloc}; @pxref{Unconstrained Allocation})
+to hold the output,
+instead of putting the output in a buffer you allocate in advance.
+A successful call to @code{aprintf} returns
+a pointer to the newly allocated string.
+
+Here is how to use @code{aprintf}
+to get the same result as the @code{snprintf} example,
+but more easily:
+
+@smallexample
+/* @r{Construct a message describing the value of a variable}
+ @r{whose name is @var{name} and whose value is @var{value}.} */
+char *
+make_message (char *name, char *value)
+@{
+ return aprintf ("value of %s is %s", name, value);
+@}
+@end smallexample
+@end deftypefun
+
@deftypefun int asprintf (char **@var{ptr}, const char *@var{template}, @dots{})
@standards{GNU, stdio.h}
@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
@@ -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 \
@@ -70,6 +70,8 @@ libc {
__isoc23_vfscanf;
__isoc23_sscanf;
__isoc23_vsscanf;
+ GLIBC_2.44 {
+ aprintf;
}
GLIBC_PRIVATE {
# global variables
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)