Re: [PATCH 3/3] tools/nolibc: add support for asprintf()

From: Thomas Weißschuh

Date: Sun Apr 05 2026 - 11:39:29 EST


On 2026-04-04 16:34:59+0100, David Laight wrote:
> On Wed, 01 Apr 2026 17:07:29 +0200
> Thomas Weißschuh <linux@xxxxxxxxxxxxxx> wrote:
>
> > Add support for dynamically allocating formatted strings through
> > asprintf() and vasprintf().
> >
> > Signed-off-by: Thomas Weißschuh <linux@xxxxxxxxxxxxxx>
> > ---
> > tools/include/nolibc/stdio.h | 50 ++++++++++++++++++++++++++++
> > tools/testing/selftests/nolibc/nolibc-test.c | 24 +++++++++++++
> > 2 files changed, 74 insertions(+)
> >
> > diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
> > index 8f7e1948a651..1c9287b558f0 100644
> > --- a/tools/include/nolibc/stdio.h
> > +++ b/tools/include/nolibc/stdio.h
> > @@ -787,6 +787,56 @@ int sprintf(char *buf, const char *fmt, ...)
> > return ret;
> > }
> >
> > +static __attribute__((unused, format(printf, 2, 0)))
> > +int __nolibc_vasprintf(char **strp, const char *fmt, va_list args1, va_list args2)
> > +{
> > + char *buf;
> > + int len;
> > +
> > + len = vsnprintf(NULL, 0, fmt, args1);
> > + if (len < 0)
> > + return -1;
>
> vsnprintf() can never fail.

The one in nolibc not, according to the specification it could.
So to be on the safe side, also against future changes in nolibc
I'd like to keep the check.
The asnprintf()/malloc() implementation will make any performance
considerations moot anyways.

> > +
> > + buf = malloc(len + 1);
> > + if (!buf)
> > + return -1;
> > +
> > + len = vsnprintf(buf, len + 1, fmt, args2);
>
> It is possible to get a different length.
> Even without threads data might come from an mmap()ed file that
> is changed by another process.
> So you need to check that the length doesn't increase.

Good point, I plan to apply the following fixup:

--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -798,8 +798,8 @@ int sprintf(char *buf, const char *fmt, ...)
static __attribute__((unused, format(printf, 2, 0)))
int __nolibc_vasprintf(char **strp, const char *fmt, va_list args1, va_list args2)
{
+ int len, len2;
char *buf;
- int len;

len = vsnprintf(NULL, 0, fmt, args1);
if (len < 0)
@@ -809,8 +809,8 @@ int __nolibc_vasprintf(char **strp, const char *fmt, va_list args1, va_list args
if (!buf)
return -1;

- len = vsnprintf(buf, len + 1, fmt, args2);
- if (len < 0) {
+ len2 = vsnprintf(buf, len + 1, fmt, args2);
+ if (len2 < 0) {
free(buf);
return -1;
}