From patchwork Wed Mar 18 21:47:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 131929 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id AEA0E4BC89B0 for ; Wed, 18 Mar 2026 21:50:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AEA0E4BC89B0 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20201202 header.b=ClBYcELd X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by sourceware.org (Postfix) with ESMTPS id 06DFF4BC898E for ; Wed, 18 Mar 2026 21:47:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 06DFF4BC898E Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=kernel.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 06DFF4BC898E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=172.105.4.254 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773870477; cv=none; b=Nuhi4qT5bUBR9plT8KaTFibsp6TJqvVl8M7L+DhnVj+jjZLdXsS84sra9hwpfCQxqSKbz7hhsUNlyrSqJa7Pl63UTdeS0c80VS78Ax83XbfekX9D7TFP0wx2pTsiOcKTU4MAXe8A8zZ3cJCg29bQUocv/BdTbIkbWn+/jnX32CU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773870477; c=relaxed/simple; bh=WvZnurWWmuH+fLKAsB5+ZAARPqIxF3Ozv97GO7d3rG0=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=NClQm2fQUaoDQjOHYNLcelyKGnQQE+oEBH8H5IwR5UIDls9OyEww4ddk4Z/abWwTMhXAYItXJaH0NT/6JfpjguXlFDsrj2165mmTc3nEzEU5dLxtaGLJF2eKBpVWReqO0esUbak6eRCzMN2UrfgIxjRzRcFDENBaWd0nWCmv28I= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 06DFF4BC898E Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 60F0360121; Wed, 18 Mar 2026 21:47:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADE1AC19421; Wed, 18 Mar 2026 21:47:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773870476; bh=WvZnurWWmuH+fLKAsB5+ZAARPqIxF3Ozv97GO7d3rG0=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=ClBYcELdHJOfR8DXzNA0Y0I2AcGDdeskBmsBjvnJPBENfI6kRy3MIGR/5KxGFc7nW yIPlE247ap2FTJu7pu8dxtbS2MzG8nmlxFdm+cbNtTm5J9y4XC8GXyT9eEkuC8JGG6 JuJgUcPTLeE0tHVc52+VYND+rGs1PsEon5tlCeuviTv6/mEE20IVF3S7cL8hqvf40C KlXPBuK/SMi/RD5oQk5MnJNf/gK74oNXBmCAm77/r94W6Uf9sd7+9JG5FMFGZX21Bh DZstfc4X+FImkywMsYYBBKOBoawjrcTvSV1nVYo8JgJwqImYfvBj9710du32nsls3E 7cxY9clM5T9Hw== Date: Wed, 18 Mar 2026 22:47:52 +0100 From: Alejandro Colomar To: libc-alpha@sourceware.org Cc: Alejandro Colomar , Joseph Myers , Paul Eggert , Adhemerval Zanella Netto , Florian Weimer , "Dmitry V. Levin" , Archie Cobbs , Solar Designer , Sam James , Bruno Haible Subject: [RFC v4 1/2] Add [v]aprintf(3) Message-ID: X-Mailer: git-send-email 2.53.0 References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org This function is fundamentally the same as asprintf(3) --which was standardized in POSIX.1-2024--. However, it has a key difference, which makes it a much better design. Instead of returning the newly allocated pointer through a char** parameter, it returns the pointer (like strdup(3)). The API is as simple as it can be: char *aprintf(const char *restrict fmt, ...); char *vaprintf(const char *restrict fmt, va_list ap); This difference has several benefits: - One less parameter. This means less source code for using this API, which implicitly means less chances of making mistakes. It is also less noise while reading code, which increases readability. Especially, we get rid of a pointer-to-pointer parameter, which are especially weird. - The function has an prototype that resembles strdup(3). This functionality is commonly paired with strdup(3) calls, because they're very related. By having a similar prototype, the code is more naturally paired with Compare: if (cond) { p = strdup("foo"); if (p == NULL) goto fail; } else { if (asprintf(&p, "foo %d", 42) < 0) goto fail; } vs p = cond ? strdup("foo") : aprintf("foo %d", 42); if (p == NULL) goto fail; - We don't need to fail with EOVERFLOW. This initial implementation still fails with EOVERFLOW, because it would require a lot of work implementing it in a way that doesn't have such a failure point, but the API has no inherent reasons to fail with EOVERFLOW. - This API returns a pointer, which makes it possible to use __attribute__((__malloc__(free))). This would allow static analysers to know that these APIs allocate memory, which would prevent memory leaks, use-after-free errors, and other common issues of handling memory. The name is similar to asprintf(3), removing the 's'. This is the same name that gnulib has used for their implementation. It also matches the name of the n3750 (alx-0007) proposal for ISO C2y. The C Committee was worried that such a non-reserved name might be unlikely to be viable, as some existing code already uses it. However: - Most code using this name, uses it with the same exact semantics. In those cases, it's not a problem. - In the remaining cases, the prototype is different, so they'll eventually get a compiler error for the clash. This is entirely safe. And by hiding the name under _GNU_SOURCE, we make that clash less likely. Once/if this is eventually standard, I expect people will adapt their code, which is entirely reasonable. Still, then the APIs will be hidden under _ISOC2Y_SOURCE et al., so this will only affect users when they opt-in to such a version. Link: Cc: Joseph Myers Cc: Paul Eggert Cc: Bruno Haible Cc: Adhemerval Zanella Netto Cc: Florian Weimer Cc: "Dmitry V. Levin" Cc: Archie Cobbs Cc: Solar Designer Cc: Sam James Signed-off-by: Alejandro Colomar --- debug/Makefile | 4 ++ debug/Versions | 3 + debug/aprintf_chk.c | 51 +++++++++++++++++ debug/vaprintf_chk.c | 39 +++++++++++++ include/stdio.h | 8 +++ libio/Makefile | 4 +- libio/Versions | 3 + libio/bits/stdio-ldbl.h | 5 ++ libio/bits/stdio2-decl.h | 8 +++ libio/bits/stdio2.h | 42 ++++++++++++++ libio/stdio.h | 13 +++++ libio/tst-aprintf.c | 57 +++++++++++++++++++ libio/vaprintf.c | 39 +++++++++++++ manual/stdio.texi | 26 +++++++++ stdio-common/Makefile | 2 + stdio-common/Versions | 2 + stdio-common/aprintf.c | 40 +++++++++++++ sysdeps/ieee754/ldbl-128ibm-compat/Makefile | 8 ++- .../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 ++++++++++ sysdeps/ieee754/ldbl-opt/Makefile | 6 ++ sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c | 17 ++++++ 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 +++ 27 files changed, 543 insertions(+), 2 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 diff --git a/debug/Makefile b/debug/Makefile index c6c1069b..765720a1 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -31,6 +31,7 @@ headers := execinfo.h routines = \ $(static-only-routines) \ ____longjmp_chk \ + aprintf_chk \ asprintf_chk \ backtrace \ backtracesyms \ @@ -94,6 +95,7 @@ routines = \ strncpy_chk \ swprintf_chk \ ttyname_r_chk \ + vaprintf_chk \ vasprintf_chk \ vdprintf_chk \ vfprintf_chk \ @@ -143,6 +145,8 @@ CFLAGS-sprintf_chk.c += $(libio-mtsafe) CFLAGS-snprintf_chk.c += $(libio-mtsafe) CFLAGS-vsprintf_chk.c += $(libio-mtsafe) CFLAGS-vsnprintf_chk.c += $(libio-mtsafe) +CFLAGS-aprintf_chk.c += $(libio-mtsafe) +CFLAGS-vaprintf_chk.c += $(libio-mtsafe) CFLAGS-asprintf_chk.c += $(libio-mtsafe) CFLAGS-vasprintf_chk.c += $(libio-mtsafe) CFLAGS-obprintf_chk.c += $(libio-mtsafe) diff --git a/debug/Versions b/debug/Versions index fc818d29..d87148f5 100644 --- a/debug/Versions +++ b/debug/Versions @@ -71,6 +71,9 @@ libc { GLIBC_2.43 { __memset_explicit_chk; } + GLIBC_2.44 { + __aprintf_chk; __vaprintf_chk; + } GLIBC_PRIVATE { __fortify_fail; } diff --git a/debug/aprintf_chk.c b/debug/aprintf_chk.c new file mode 100644 index 00000000..30f7811f --- /dev/null +++ b/debug/aprintf_chk.c @@ -0,0 +1,51 @@ +/* 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 + . */ + +#include +#include + + +/* Write formatted output from FORMAT to a string allocated with malloc. */ +char * +___aprintf_chk (int flag, const char *fmt, ...) +{ + /* For flag > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n + can only come from read-only format strings. */ + unsigned int mode = (flag > 0) ? PRINTF_FORTIFY : 0; + va_list ap; + char *p; + + va_start (ap, fmt); + if (__vasprintf_internal (&p, fmt, ap, mode) < 0) + p = NULL; + va_end (ap); + + return p; +} +#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 +/* This is needed since is included in this case, leading to + * multiple asm redirection of the same symbol + */ +ldbl_hidden_def (___aprintf_chk, __aprintf_chk) +ldbl_strong_alias (___aprintf_chk, __aprintf_chk) +#else +/* On some systems introduction of ldbl_* macros lead to ABI breakage due to the + * long_double_symbol aliasing. + */ +strong_alias (___aprintf_chk, __aprintf_chk) +libc_hidden_def (__aprintf_chk) +#endif diff --git a/debug/vaprintf_chk.c b/debug/vaprintf_chk.c new file mode 100644 index 00000000..1ca96633 --- /dev/null +++ b/debug/vaprintf_chk.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 + . + + 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 + +char * +__vaprintf_chk (int flag, const char *fmt, va_list ap) +{ + /* For flag > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n + can only come from read-only format strings. */ + unsigned int mode = (flag > 0) ? PRINTF_FORTIFY : 0; + char *p; + + return __vasprintf_internal (&p, fmt, ap, mode) < 0 ? NULL : p; +} +libc_hidden_def (__vaprintf_chk) diff --git a/include/stdio.h b/include/stdio.h index 88166993..cfdec368 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -77,6 +77,11 @@ extern int __vfprintf_chk (FILE *, int, const char *, __gnuc_va_list); stdio_hidden_ldbl_proto (__, vfprintf_chk) 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__; +extern char *__vaprintf_chk (int, const char *, __gnuc_va_list) + __THROW __attribute_malloc__; +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; stdio_hidden_ldbl_proto (__, vasprintf_chk) @@ -239,6 +244,7 @@ extern const size_t _sys_errlist_internal_len attribute_hidden; extern const char *__get_errlist (int) attribute_hidden; extern const char *__get_errname (int) attribute_hidden; +libc_hidden_ldbl_proto (__aprintf) libc_hidden_ldbl_proto (__asprintf) # if IS_IN (libc) @@ -317,8 +323,10 @@ rtld_hidden_proto (__libc_fatal) libc_hidden_proto (__fgets_unlocked_chk) #if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 +libc_hidden_ldbl_proto (__aprintf_chk) libc_hidden_ldbl_proto (__asprintf_chk) #else +libc_hidden_proto (__aprintf_chk) libc_hidden_proto (__asprintf_chk) #endif diff --git a/libio/Makefile b/libio/Makefile index 08e1e0ec..b345f806 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 \ @@ -62,6 +62,7 @@ routines_no_fortify += \ iofgetws_u \ iovdprintf \ swprintf \ + vaprintf \ vasprintf \ vsnprintf \ vswprintf \ @@ -89,6 +90,7 @@ tests = \ test-fmemopen \ test-fputs-unbuffered-full \ test-fputws-unbuffered-full \ + tst-aprintf \ tst-asprintf-null \ tst-atime \ tst-bz22415 \ diff --git a/libio/Versions b/libio/Versions index b91a7bc9..48ffe3d3 100644 --- a/libio/Versions +++ b/libio/Versions @@ -155,6 +155,9 @@ libc { # f* fmemopen; } + GLIBC_2.44 { + vaprintf; + } GLIBC_PRIVATE { # Used by NPTL and librt __libc_fatal; diff --git a/libio/bits/stdio-ldbl.h b/libio/bits/stdio-ldbl.h index 3cbff14e..3b805b3e 100644 --- a/libio/bits/stdio-ldbl.h +++ b/libio/bits/stdio-ldbl.h @@ -99,6 +99,9 @@ __LDBL_REDIR_DECL (dprintf) #endif #ifdef __USE_GNU +__LDBL_REDIR_DECL (vaprintf) +__LDBL_REDIR2_DECL (aprintf) +__LDBL_REDIR_DECL (aprintf) __LDBL_REDIR_DECL (vasprintf) __LDBL_REDIR2_DECL (asprintf) __LDBL_REDIR_DECL (asprintf) @@ -123,6 +126,8 @@ __LDBL_REDIR2_DECL (dprintf_chk) __LDBL_REDIR2_DECL (vdprintf_chk) # endif # ifdef __USE_GNU +__LDBL_REDIR2_DECL (aprintf_chk) +__LDBL_REDIR2_DECL (vaprintf_chk) __LDBL_REDIR2_DECL (asprintf_chk) __LDBL_REDIR2_DECL (vasprintf_chk) __LDBL_REDIR2_DECL (obstack_printf_chk) diff --git a/libio/bits/stdio2-decl.h b/libio/bits/stdio2-decl.h index ada092ea..cf52c46c 100644 --- a/libio/bits/stdio2-decl.h +++ b/libio/bits/stdio2-decl.h @@ -66,6 +66,14 @@ extern int __vdprintf_chk (int __fd, int __flag, # ifdef __USE_GNU +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 __ap) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))) + __attribute_malloc__; extern int __asprintf_chk (char **__restrict __ptr, int __flag, const char *__restrict __fmt, ...) __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur; diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h index 193494db..b9fed67e 100644 --- a/libio/bits/stdio2.h +++ b/libio/bits/stdio2.h @@ -200,6 +200,18 @@ vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __ap) # ifdef __USE_GNU # ifdef __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 (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...)) { @@ -223,6 +235,26 @@ __NTH (obstack_printf (struct obstack *__restrict __obstack, __va_arg_pack ()); } # elif __fortify_use_clang +__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 (asprintf (__fortify_clang_overload_arg (char **, __restrict, __ptr), const char *__restrict __fmt, ...)) @@ -260,6 +292,10 @@ __NTH (obstack_printf (__fortify_clang_overload_arg (struct obstack *, return __r; } # elif !defined __cplusplus +# define aprintf(...) \ + __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__) +# define __aprintf(...) \ + __aprintf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__) # define asprintf(ptr, ...) \ __asprintf_chk (ptr, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__) # define __asprintf(ptr, ...) \ @@ -268,6 +304,12 @@ __NTH (obstack_printf (__fortify_clang_overload_arg (struct obstack *, __obstack_printf_chk (obstack, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__) # endif +__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 (vasprintf (char **__restrict __ptr, const char *__restrict __fmt, __gnuc_va_list __ap)) diff --git a/libio/stdio.h b/libio/stdio.h index 3bf6a1f6..81d7176c 100644 --- a/libio/stdio.h +++ b/libio/stdio.h @@ -412,6 +412,19 @@ 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 __fmt, __gnuc_va_list __ap) + __THROWNL __attribute__ ((__format__ (__printf__, 1, 0))) + __attribute_malloc__; +extern char *__aprintf (const char *__restrict __fmt, ...) + __THROWNL __attribute__ ((__format__ (__printf__, 1, 2))) + __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, diff --git a/libio/tst-aprintf.c b/libio/tst-aprintf.c new file mode 100644 index 00000000..e10eb591 --- /dev/null +++ b/libio/tst-aprintf.c @@ -0,0 +1,57 @@ +/* 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 + . */ + +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + char *buf; + + /* Success */ + buf = aprintf ("foo %d", 42); + TEST_COMPARE_STRING (buf, "foo 42"); + free(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); + + return 0; +} + +#include diff --git a/libio/vaprintf.c b/libio/vaprintf.c new file mode 100644 index 00000000..157f783d --- /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 + . + + 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 +#include +#include +#include + +char * +__vaprintf (const char *fmt, va_list ap) +{ + char *p; + + return __vasprintf_internal (&p, fmt, ap, 0) < 0 ? NULL : p; +} +ldbl_weak_alias (__vaprintf, vaprintf) diff --git a/manual/stdio.texi b/manual/stdio.texi index c01feaed..e7deca78 100644 --- a/manual/stdio.texi +++ b/manual/stdio.texi @@ -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{}}} diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 21094483..9a26773e 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -89,6 +89,7 @@ routines := \ _fitoa_word \ _itoa \ _itowa \ + aprintf \ asprintf \ ctermid \ cuserid \ @@ -177,6 +178,7 @@ routines := \ # Exclude fortified routines from being built with _FORTIFY_SOURCE routines_no_fortify += \ + aprintf \ asprintf \ dprintf \ fprintf \ diff --git a/stdio-common/Versions b/stdio-common/Versions index 8e1cbf85..aee611b2 100644 --- a/stdio-common/Versions +++ b/stdio-common/Versions @@ -70,6 +70,8 @@ libc { __isoc23_vfscanf; __isoc23_sscanf; __isoc23_vsscanf; + GLIBC_2.44 { + aprintf; } GLIBC_PRIVATE { # global variables diff --git a/stdio-common/aprintf.c b/stdio-common/aprintf.c new file mode 100644 index 00000000..bee49667 --- /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 + . */ + +#include +#include + +/* 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) diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/Makefile b/sysdeps/ieee754/ldbl-128ibm-compat/Makefile index 10ae73db..e0989a51 100644 --- a/sysdeps/ieee754/ldbl-128ibm-compat/Makefile +++ b/sysdeps/ieee754/ldbl-128ibm-compat/Makefile @@ -5,6 +5,7 @@ ldbl-extra-routines += fwscanf \ swscanf \ swprintf \ wscanf \ + vaprintf \ vasprintf \ vdprintf \ vscanf \ @@ -40,6 +41,7 @@ endif ifeq ($(subdir),stdio-common) ldbl-extra-routines += printf_size \ + aprintf \ asprintf \ dprintf \ fprintf \ @@ -250,12 +252,14 @@ $(objpfx)test-printf-size-ibm128.out: \ endif ifeq ($(subdir),debug) -ldbl-extra-routines += asprintf_chk \ +ldbl-extra-routines += aprintf_chk \ + asprintf_chk \ dprintf_chk \ fprintf_chk \ printf_chk \ snprintf_chk \ sprintf_chk \ + vaprintf_chk \ vasprintf_chk \ vdprintf_chk \ vfprintf_chk \ @@ -480,6 +484,7 @@ endif routines += $(foreach r,$(ldbl-extra-routines),ieee128-$(r)) routines_no_fortify += \ + ieee128-aprintf \ ieee128-asprintf \ ieee128-dprintf \ ieee128-fprintf \ @@ -490,6 +495,7 @@ routines_no_fortify += \ ieee128-sprintf \ ieee128-swprintf \ ieee128-syslog \ + ieee128-vaprintf \ ieee128-vasprintf \ ieee128-vdprintf \ ieee128-vfprintf \ diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf.c new file mode 100644 index 00000000..041ebc01 --- /dev/null +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf.c @@ -0,0 +1,36 @@ +/* Wrapper for aprintf. IEEE128 version. + 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 + . */ + +#include +#include + +extern char * +___ieee128___aprintf (const char *fmt, ...) +{ + va_list ap; + char *p; + + va_start (ap, fmt); + if (__vasprintf_internal (&p, fmt, ap, PRINTF_LDBL_USES_FLOAT128) < 0) + p = NULL; + va_end (ap); + + return p; +} +hidden_def (___ieee128___aprintf) +strong_alias (___ieee128___aprintf, __aprintfieee128) diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf_chk.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf_chk.c new file mode 100644 index 00000000..0e1e395d --- /dev/null +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-aprintf_chk.c @@ -0,0 +1,40 @@ +/* Wrapper for __aprintf_chk. IEEE128 version. + 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 + . */ + +#include +#include + +extern char * +___ieee128___aprintf_chk (int flag, const char *fmt, ...) +{ + va_list ap; + char *p; + + unsigned int mode = PRINTF_LDBL_USES_FLOAT128; + if (flag > 0) + mode |= PRINTF_FORTIFY; + + va_start (ap, fmt); + if (__vasprintf_internal (&p, fmt, ap, mode) < 0) + p = NULL; + va_end (ap); + + return p; +} +hidden_def (___ieee128___aprintf_chk) +strong_alias (___ieee128___aprintf_chk, __aprintf_chkieee128) diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf.c new file mode 100644 index 00000000..6157f306 --- /dev/null +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf.c @@ -0,0 +1,29 @@ +/* Wrapper for vaprintf. IEEE128 version. + 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 + . */ + +#include + +extern char * +___ieee128_vaprintf (const char *fmt, va_list ap) +{ + char *p; + if (__vasprintf_internal (&p, fmt, ap, PRINTF_LDBL_USES_FLOAT128) < 0) + p = NULL; + return p; +} +strong_alias (___ieee128_vaprintf, __vaprintfieee128) diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf_chk.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf_chk.c new file mode 100644 index 00000000..4fd0ca8c --- /dev/null +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vaprintf_chk.c @@ -0,0 +1,31 @@ +/* Wrapper for __vaprintf_chk. IEEE128 version. + 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 + . */ + +#include + +extern char * +___ieee128___vaprintf_chk (int flag, const char *fmt, va_list ap) +{ + char *p; + unsigned int mode = PRINTF_LDBL_USES_FLOAT128; + if (flag > 0) + mode |= PRINTF_FORTIFY; + + return __vasprintf_internal (&p, fmt, ap, mode) < 0 ? NULL : p; +} +strong_alias (___ieee128___vaprintf_chk, __vaprintf_chkieee128) diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile index ef7da1f8..3effc4ef 100644 --- a/sysdeps/ieee754/ldbl-opt/Makefile +++ b/sysdeps/ieee754/ldbl-opt/Makefile @@ -15,6 +15,8 @@ libnldbl-calls = \ acos \ acosh \ acospi \ + aprintf \ + aprintf_chk \ asin \ asinh \ asinpi \ @@ -223,6 +225,8 @@ libnldbl-calls = \ trunc \ ufromfp \ ufromfpx \ + vaprintf \ + vaprintf_chk \ vasprintf \ vasprintf_chk \ vdprintf \ @@ -556,6 +560,7 @@ CFLAGS-tst-nldbl-wscanf-binary-gnu89.c += -mlong-double-64 -std=gnu89 \ endif routines_no_fortify += \ + nldbl-aprintf \ nldbl-asprintf \ nldbl-dprintf \ nldbl-fprintf \ @@ -567,6 +572,7 @@ routines_no_fortify += \ nldbl-sprintf \ nldbl-swprintf \ nldbl-syslog \ + nldbl-vaprintf \ nldbl-vasprintf \ nldbl-vdprintf \ nldbl-vfprintf \ diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c b/sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c new file mode 100644 index 00000000..fe250c03 --- /dev/null +++ b/sysdeps/ieee754/ldbl-opt/nldbl-aprintf.c @@ -0,0 +1,17 @@ +#include "nldbl-compat.h" + +attribute_hidden +char * +__aprintf (const char *fmt, ...) +{ + va_list ap; + char *p; + + va_start (ap, fmt); + p = __nldbl_vaprintf (fmt, ap); + va_end (ap); + + return p; +} +extern __typeof (__aprintf) aprintf attribute_hidden; +weak_alias (__aprintf, aprintf) diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-aprintf_chk.c b/sysdeps/ieee754/ldbl-opt/nldbl-aprintf_chk.c new file mode 100644 index 00000000..77b1d221 --- /dev/null +++ b/sysdeps/ieee754/ldbl-opt/nldbl-aprintf_chk.c @@ -0,0 +1,15 @@ +#include "nldbl-compat.h" + +attribute_hidden +char * +__aprintf_chk (int flag, const char *fmt, ...) +{ + va_list ap; + char *p; + + va_start (ap, fmt); + p = __nldbl___vaprintf_chk (flag, fmt, ap); + va_end (ap); + + return p; +} diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c new file mode 100644 index 00000000..6ba7789c --- /dev/null +++ b/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf.c @@ -0,0 +1,9 @@ +#include "nldbl-compat.h" + +attribute_hidden +weak_function +char * +vaprintf (const char *fmt, va_list ap) +{ + return __nldbl_vaprintf (fmt, ap); +} diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf_chk.c b/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf_chk.c new file mode 100644 index 00000000..72e4fca7 --- /dev/null +++ b/sysdeps/ieee754/ldbl-opt/nldbl-vaprintf_chk.c @@ -0,0 +1,8 @@ +#include "nldbl-compat.h" + +attribute_hidden +char * +__vaprintf_chk (int flag, const char *fmt, va_list ap) +{ + return __nldbl___vaprintf_chk (flag, fmt, ap); +} From patchwork Wed Mar 18 21:47:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 131928 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 98D854B35896 for ; Wed, 18 Mar 2026 21:49:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 98D854B35896 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20201202 header.b=LkZ7cVIT X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from tor.source.kernel.org (tor.source.kernel.org [IPv6:2600:3c04:e001:324:0:1991:8:25]) by sourceware.org (Postfix) with ESMTPS id F0E0F4BCA41F for ; Wed, 18 Mar 2026 21:48:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F0E0F4BCA41F Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=kernel.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F0E0F4BCA41F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2600:3c04:e001:324:0:1991:8:25 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773870481; cv=none; b=g/uIVDjJaR8f6v/a27A84vFXucc+kmZt84z3I7bVhTQ9lEmznmjXz0/FUtrO5i0vO6iQzUsFlWU7DtDzBsHfd9whvi1OtQr0upw5unSaHS8DGwi1HP+BPG3sN1pG0WFpAos5HC17G5yfzBtsxnbspUTD3sa1ykrRhLCXZPmkvhs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773870481; c=relaxed/simple; bh=EZ/H9xyt77P5+NsOB/rSSC6qIH3qGLiuF1/Fy0HdrPs=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=WuyUFNpb0mLB9eJ0nCVIwvShuspkVANxabeXw6SguGkfId3YdarX/CJUE7vmOrt6jALRD9A/hflw0h6QsrBcOh0sciAW7beNaqmDqAK58EpZ+WzB80xrsvOD+KHiwShs7kBtPTb9nQUiCi+DmltXbw3ecP3bMde2O5DrznpWmTY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F0E0F4BCA41F Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 8195060133; Wed, 18 Mar 2026 21:48:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 296E2C19421; Wed, 18 Mar 2026 21:47:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773870480; bh=EZ/H9xyt77P5+NsOB/rSSC6qIH3qGLiuF1/Fy0HdrPs=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=LkZ7cVITV1rP7eCNgjBAYFqzUzCLC8fZJvQfUMJZflPBgBBzGY0JS1Mwpw56jJ8kz pLgeZuZc8yxKD8aqlxEdAcMvirtjAi3P/Wh1SAX7PQh+C+GY+fmChlafXO7iqWVuoW sBKoegegNr+uhHR9dOq3uWbSdKIqCefGSIGOglsW2BsJx98OvG7rxpGCGTuSXE3tWw bSU6Lr1v9xSgkniMpqfg2l40mc4mh2UdQA/V6cZGCZenXKQGjd8ENPRBveNfSZ/OCR MOahW0QhfstreWqbVkBUt5jxQT/omzUyrjbO+gnxVi4TGs6QHDzk0MlTZZkWlpMZJR s2iVr6TEJ/Aig== Date: Wed, 18 Mar 2026 22:47:56 +0100 From: Alejandro Colomar To: libc-alpha@sourceware.org Cc: Alejandro Colomar , Joseph Myers , Paul Eggert , Adhemerval Zanella Netto , Florian Weimer , "Dmitry V. Levin" , Archie Cobbs , Solar Designer , Sam James Subject: [RFC v4 2/2] manual/: Prefer aprintf(3) over asprintf(3) Message-ID: X-Mailer: git-send-email 2.53.0 References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-10.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org While it's less portable at the moment, it's a better API (simpler, safer, and less error-prone). The C Committee has expressed strong support for this API, intending to standardize it. Thus, it should be more portable in the long term. Signed-off-by: Alejandro Colomar --- manual/examples/rprintf.c | 4 ++-- manual/stdio.texi | 4 ++-- manual/string.texi | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/manual/examples/rprintf.c b/manual/examples/rprintf.c index 734a8768..736ac169 100644 --- a/manual/examples/rprintf.c +++ b/manual/examples/rprintf.c @@ -38,8 +38,8 @@ print_widget (FILE *stream, /* Format the output into a string. */ w = *((const Widget **) (args[0])); - len = asprintf (&buffer, "", w, w->name); - if (len == -1) + buffer = aprintf ("", w, w->name); + if (buffer == NULL) return -1; /* Pad to the minimum field width and print to the stream. */ diff --git a/manual/stdio.texi b/manual/stdio.texi index e7deca78..91149626 100644 --- a/manual/stdio.texi +++ b/manual/stdio.texi @@ -2458,7 +2458,7 @@ because it can potentially output more characters than can fit in the allocation size of the string @var{s}. Remember that the field width given in a conversion specification is only a @emph{minimum} value. -To avoid this problem, you can use @code{snprintf} or @code{asprintf}, +To avoid this problem, you can use @code{snprintf} or @code{aprintf}, described below. @end deftypefun @@ -2543,7 +2543,7 @@ make_message (char *name, char *value) @end group @end smallexample -In practice, it is often easier just to use @code{asprintf}, below. +In practice, it is often easier just to use @code{aprintf}, below. @strong{Attention:} In versions of @theglibc{} prior to 2.1 the return value is the number of characters stored, not including the diff --git a/manual/string.texi b/manual/string.texi index 24004f1f..7a6ee12a 100644 --- a/manual/string.texi +++ b/manual/string.texi @@ -1198,7 +1198,7 @@ strings to fit arbitrary size limits. @xref{Semantics, , Writing Robust Programs, standards, The GNU Coding Standards}. Instead of string-truncation functions, it is usually better to use dynamic memory allocation (@pxref{Unconstrained Allocation}) and functions -such as @code{strdup} or @code{asprintf} to construct strings. +such as @code{strdup} or @code{aprintf} to construct strings. @node String/Array Comparison @section String/Array Comparison