| Message ID | cover.1773857304.git.alx@kernel.org (mailing list archive) |
|---|---|
| Headers |
Return-Path: <libc-alpha-bounces~patchwork=sourceware.org@sourceware.org> 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 032994BC89B0 for <patchwork@sourceware.org>; Wed, 18 Mar 2026 18:16:08 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 032994BC89B0 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=VRtIq9pu X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from sea.source.kernel.org (sea.source.kernel.org [IPv6:2600:3c0a:e001:78e:0:1991:8:25]) by sourceware.org (Postfix) with ESMTPS id 064564BBC0BC for <libc-alpha@sourceware.org>; Wed, 18 Mar 2026 18:15:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 064564BBC0BC 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 064564BBC0BC Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2600:3c0a:e001:78e:0:1991:8:25 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773857703; cv=none; b=ll4OwWL0caI0h5ihv4HZyheOHZ1xCUqQ+egpUTMXaWSbPo9CsvTBwFhdMp6o41ekzrVR0UtRBBjCQs64EWIFzfNF6bsl7AvHDFBi4VJ5q9f5eqNA9Rdypg83/bSHP8nE3buXCw0cRCCemk34VnmsmYvyC2tPu57xu4Ga2QHOPVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773857703; c=relaxed/simple; bh=fa9vzI9ajldCs/feQEouOU8H280OaEcz0Bhbp7WKpNI=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=EoE7JOXMeXb2P1uyXZOgeHMhRAaxpVOwh3U7cOu5UhTlPNpqJItZFRT0evj4NPLHoCobN8oJeBiysc2E/EqXQe1+ZrSkjUfC+nlehHy0BIDkiWD2yzhwfVCvtumDTxNryDhb/yUG5D6vEUomqoc/F+AYZwGg8/ulynX5xBG39L4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 064564BBC0BC Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 0674844243; Wed, 18 Mar 2026 18:15:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEA46C19421; Wed, 18 Mar 2026 18:14:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773857700; bh=fa9vzI9ajldCs/feQEouOU8H280OaEcz0Bhbp7WKpNI=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=VRtIq9pudDVLIkHNnIv0YUtXZ/a/cJQTZ/wpey8amaSf9Ddg78zIbvSimTT+WD74J Dq7nBstfLEoKhoY7l6PUj9pKFb+XOguCGDcngKJkEbnMWxz9jzjRvUnhCHUVIDbvFp 6lhVrOaSr6gOgwud0BJwE3TVlatdhrABcss8xIon2GYALBTc7vG/YsVIM2fyLvkEKR ZgmeLe52Ft0nlrfHOwP6fZ/V4xOKcG54m2nXGHkRJeWxUjI29uiTBEPHvsUZBMzZn8 u/CCNO8VuvnTmMWAFSeGNBeD0PqEHSA07o7kGjMzQfqeNhUHq+dUh2KqdcX3YlAbYy lLyYoKElwgyjA== Date: Wed, 18 Mar 2026 19:14:56 +0100 From: Alejandro Colomar <alx@kernel.org> To: libc-alpha@sourceware.org Cc: Alejandro Colomar <alx@kernel.org>, Joseph Myers <josmyers@redhat.com>, Paul Eggert <eggert@cs.ucla.edu>, Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>, Florian Weimer <fweimer@redhat.com>, "Dmitry V. Levin" <ldv@altlinux.org>, Archie Cobbs <archie.cobbs@gmail.com>, Solar Designer <solar@openwall.com>, Sam James <sam@gentoo.org> Subject: [RFC v3 0/2] Add [v]aprintf(3) Message-ID: <cover.1773857304.git.alx@kernel.org> X-Mailer: git-send-email 2.53.0 References: <916855e5ad90ca3611a235ecbcf08a1359771eb9.1773775432.git.alx@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <abSVWeS3nHmkZSKn@devuan> X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_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 <libc-alpha.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/libc-alpha/> List-Post: <mailto:libc-alpha@sourceware.org> List-Help: <mailto:libc-alpha-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=subscribe> Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org |
| Series |
Add [v]aprintf(3)
|
|
Message
Alejandro Colomar
March 18, 2026, 6:14 p.m. UTC
Hi!
I've added docs, some tests, and fortified versions. Doing regression
testing shows that the newly added tests are okay, but I somehow broke
the Makefiles.
$ diff -u ../.tmp.master/tests.sum tests.sum
--- ../.tmp.master/tests.sum 2026-03-18 18:52:49.914978699 +0100
+++ tests.sum 2026-03-18 18:27:58.265965856 +0100
@@ -7,7 +7,7 @@
PASS: check-local-headers
PASS: check-wrapper-headers
PASS: link-static-libc
-PASS: lint-makefiles
+FAIL: lint-makefiles
Running argp ...
PASS: argp/argp-test
@@ -1936,6 +1936,7 @@
PASS: libio/test-fputs-unbuffered-full
PASS: libio/test-fputws-unbuffered-full
PASS: libio/test-freopen
+PASS: libio/tst-aprintf
PASS: libio/tst-asprintf-null
PASS: libio/tst-atime
PASS: libio/tst-bz22415
However, I don't know how I broke 'lint-makefiles'. Where's the log for
consulting the details of this?
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?
Also, is there anything else I should do?
Of course, I plan to fill the commit messages more. I still haven't
started with that part.
See the range-diff at the bottom, for the changes in this revision.
Have a lovely day!
Alex
Alejandro Colomar (2):
Add [v]aprintf(3)
manual/: Prefer aprintf(3) over asprintf(3)
debug/Versions | 3 +++
include/stdio.h | 3 +++
libio/Makefile | 4 ++-
libio/Versions | 3 +++
libio/bits/stdio-ldbl.h | 2 ++
libio/bits/stdio2-decl.h | 8 ++++++
libio/bits/stdio2.h | 42 +++++++++++++++++++++++++++++
libio/stdio.h | 10 +++++++
libio/tst-aprintf.c | 56 +++++++++++++++++++++++++++++++++++++++
libio/vaprintf.c | 39 +++++++++++++++++++++++++++
manual/examples/rprintf.c | 4 +--
manual/stdio.texi | 30 +++++++++++++++++++--
manual/string.texi | 2 +-
stdio-common/Makefile | 2 ++
stdio-common/Versions | 2 ++
stdio-common/aprintf.c | 40 ++++++++++++++++++++++++++++
16 files changed, 244 insertions(+), 6 deletions(-)
create mode 100644 libio/tst-aprintf.c
create mode 100644 libio/vaprintf.c
create mode 100644 stdio-common/aprintf.c
Range-diff against v2:
1: 916855e5 ! 1: f616528f Add [v]aprintf(3)
@@ Commit message
Signed-off-by: Alejandro Colomar <alx@kernel.org>
+ ## debug/Versions ##
+@@ debug/Versions: libc {
+ GLIBC_2.43 {
+ __memset_explicit_chk;
+ }
++ GLIBC_2.44 {
++ __aprintf_chk; __vaprintf_chk;
++ }
+ GLIBC_PRIVATE {
+ __fortify_fail;
+ }
+
+ ## include/stdio.h ##
+@@ include/stdio.h: 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)
+
## libio/Makefile ##
@@ libio/Makefile: routines := \
\
@@ libio/Makefile: routines_no_fortify += \
vsnprintf \
vswprintf \
vwprintf \
+@@ libio/Makefile: tests = \
+ test-fputs-unbuffered-full \
+ test-fputws-unbuffered-full \
+ tst-asprintf-null \
++ tst-aprintf \
+ tst-atime \
+ tst-bz22415 \
+ tst-bz24051 \
+
+ ## libio/Versions ##
+@@ libio/Versions: libc {
+ # f*
+ fmemopen;
+ }
++ GLIBC_2.44 {
++ vaprintf;
++ }
+ GLIBC_PRIVATE {
+ # Used by NPTL and librt
+ __libc_fatal;
+
+ ## libio/bits/stdio-ldbl.h ##
+@@ libio/bits/stdio-ldbl.h: __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
+
+ ## libio/bits/stdio2-decl.h ##
+@@ libio/bits/stdio2-decl.h: 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,
+ ...)
+
+ ## libio/bits/stdio2.h ##
+@@ libio/bits/stdio2.h: __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, ...))
+@@ libio/bits/stdio2.h: __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),
+@@ libio/bits/stdio2.h: __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
+@@ libio/bits/stdio2.h: __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))
## libio/stdio.h ##
-@@ libio/stdio.h: extern int __asprintf (char **__restrict __ptr,
- extern int asprintf (char **__restrict __ptr,
- const char *__restrict __fmt, ...)
+@@ libio/stdio.h: 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)))
@@ libio/stdio.h: extern int __asprintf (char **__restrict __ptr,
+extern char *aprintf (const char *__restrict __fmt, ...)
+ __THROWNL __attribute__ ((__format__ (__printf__, 1, 2)))
+ __attribute_malloc__;
- #endif
-
++#endif
++
#ifdef __USE_XOPEN2K8
+ /* Write formatted output to a file descriptor. */
+ extern int vdprintf (int __fd, const char *__restrict __fmt,
+
+ ## libio/tst-aprintf.c (new) ##
+@@
++/* 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>
## libio/vaprintf.c (new) ##
@@
@@ libio/vaprintf.c (new)
+}
+ldbl_weak_alias (__vaprintf, vaprintf)
+ ## manual/stdio.texi ##
+@@ manual/stdio.texi: 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{}}}
+
## stdio-common/Makefile ##
@@ stdio-common/Makefile: routines := \
_itoa \
@@ stdio-common/Makefile: routines := \
fprintf \
printf \
+ ## stdio-common/Versions ##
+@@ stdio-common/Versions: libc {
+ __isoc23_vfscanf;
+ __isoc23_sscanf;
+ __isoc23_vsscanf;
++ GLIBC_2.44 {
++ aprintf;
+ }
+ GLIBC_PRIVATE {
+ # global variables
+
## stdio-common/aprintf.c (new) ##
@@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
@@ stdio-common/aprintf.c (new)
+
+ return p;
+}
-+ldbl_hidden_def (__aprintf, aprintf)
++ldbl_hidden_def (___aprintf, __aprintf)
+
+ldbl_strong_alias (___aprintf, __aprintf)
+ldbl_weak_alias (___aprintf, aprintf)
-: -------- > 2: 131b1f0c manual/: Prefer aprintf(3) over asprintf(3)
base-commit: 9da7ad6d74700811c9b4c82b5f5eb555e39241a7