[RFC v1] libio/: Add [v]aprintf()
Alejandro Colomar
alx@kernel.org
Wed Mar 18 01:17:42 GMT 2026
Hi Adhemerval,
On 2026-03-17T16:56:24-0300, Adhemerval Zanella Netto wrote:
>
>
> On 17/03/26 16:40, Alejandro Colomar wrote:
> > Hi Adhemerval,
> >
> > On 2026-03-17T16:26:06-0300, Adhemerval Zanella Netto wrote:
> >>
> >>> Projects have come up with APIs for this over time. GNU and the
> >>> BSDs have it as asprintf(3), but there seems to be consensus
> >>> that this API isn't very well designed; evidence of this is that
> >>> the behavior is slightly different in the various
> >>> implementations, and has changes through history.
> >>
> >> Could you add more details of what is wrong with the current asprintf glibc
> >> implementation, besides the initial designed limitation ('int' return i
> >> nstead of ssize_t)?
> >>
> >> We don't have any bugs against asprintf on glibc bugzilla.
> >
> > Here are three issues of asprintf(3) from the top of my head:
> >
> > - Quite often, it's used together with strdup(3) in some conditional.
> > Compare:
> >
> > if (cond) {
> > dup = strdup(s)
> > if (dup == NULL)
> > goto fail;
> > } else {
> > if (asprintf(&dup, "...", s, ...) < 0)
> > goto fail;
> > }
> > vs
> > if (cond)
> > dup = strdup(s);
> > else
> > dup = aprintf("...", s, ...);
> > if (dup == NULL)
> > goto fail;
> >
> > The code using aprintf(3) is much simpler and more readable. This
> > means it has less chances of having bugs.
> >
> > And even in uses not tied to strdup(3), the double-pointer weirdness
> > make it unnecessarily complex.
> >
> > - Some BSDs guarantee that asprintf(3) sets the pointer to NULL on
> > error. When porting BSD code to GNU, that could result in bugs
> > (reding an uninitialized pointer). I expect this to be unlikely,
> > because why would one ever use the pointer after the call failed, but
> > not impossible.
Actually, while working on the documentation of aprintf(3), I was
git-blame(1)ing the current documentation of asprintf(3), and I found
that people have actually been bitten by this. It seems to be a real
issue.
commit cb4692ce1edd5a81c2521de49dfef6125141d1c7
Author: Florian Weimer <fweimer@redhat.com>
Date: 2024-12-27 09:17:41 +0100
libio: asprintf should write NULL upon failure
This was suggested most recently by Solar Designer, noting
that code replacing vsprintf with vasprintf in a security fix
was subtly wrong:
Re: GStreamer Security Advisory 2024-0003: Orc compiler
stack-based buffer overflow
<https://www.openwall.com/lists/oss-security/2024/07/26/2>
Previous libc-alpha discussions:
I: [PATCH] asprintf error handling fix
<https://inbox.sourceware.org/libc-alpha/20011205185828.GA8376@ldv.office.alt-linux.org/>
asprintf() issue
<https://inbox.sourceware.org/libc-alpha/CANSoFxt-cdc-+C4u-rTENMtY4X9RpRSuv+axDswSPxbDgag8_Q@mail.gmail.com/>
I don't think we need a compatibility symbol for this. As the
GStreamer example shows, this change is much more likely to fix bugs
than cause compatibility issues.
Suggested-by: Dmitry V. Levin <ldv@altlinux.org>
Suggested-by: Archie Cobbs <archie.cobbs@gmail.com>
Suggested-by: Solar Designer <solar@openwall.com>
Reviewed-by: Sam James <sam@gentoo.org>
I've added these people to CC.
> >
> > - aprintf(3), by returning the newly allocated pointer, allows using
> > [[gnu::malloc(free)]], which would improve static analysis, being
> > able to detect leaks, double-free's, and other related bugs.
>
> I would say this the only compelling reason to provide this symbol, since
> the first is a more a stylist one (and subject to endless discussion), and
> second I would consider a user error instead of a glibc one.
I tend to agree, but users make mistakes if APIs allow them to, and the
asprintf(3) API was unnecessarily promoting them. aprintf(3) is free of
such issues, by design.
Have a lovely night!
Alex
>
> >
> >> On 17/03/26 15:59, Alejandro Colomar wrote:
> >>> Signed-off-by: Alejandro Colomar <alx@kernel.org>
> >>> ---
> >>>
> >>> Hi Paul, Joseph,
> >>>
> >>> Since nobody replied, I guess people are not strongly opposed to it, but
> >>> they probably want to see a patch before spending time with this.
> >>>
> >>> Thus, I've written a patch (or a draft of a patch).
> >>>
> >>> This is the first time I add a function to glibc, and I find it quite
> >>> difficult, so I'll need some help. I've added the most obvious pieces:
> >>> the prototypes and the implementation. However, this doesn't work at
> >>> all, so I guess I'm missing stuff. Would you mind helping me figure out
> >>> what I'm missing (or what's wrong)?
> >>>
> >>> I tried building this simple test program, but I get linker errors:
> >>
> >> You need to export the symbol by adding a version tag and its name on
> >> stdio-common/Versions.
> >
> > Thanks! I'll try.
> >
> >> I don't have a strong opinion about this, albeit since gnulib is already
> >> providing and that committee has shown interest I would way for C standard
> >> inclusion.
> >
> > I don't think we want that. The committee is bad at choosing names, and
> > would probably end up choosing a bad name. Now that we're in time to
> > pick a name before the committee decides, we should do it, and then tell
> > the committee about it so that it uses the same name.
> >
> > In fact, gnulib added it as aprintf(3) precisely for that reason.
>
> I would refrain to make this kind of judgement ("bad at choosing names") because
> it only adds contention on discussing a technical inclusion.
>
> Before adding this it would be helpful to hear other maintainers, but I inclined
> to consider this addition.
>
--
<https://www.alejandro-colomar.es>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260318/2abaa9ae/attachment.sig>
More information about the Libc-alpha
mailing list