]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tools/nolibc: add support for asprintf()
authorThomas Weißschuh <linux@weissschuh.net>
Wed, 1 Apr 2026 15:07:29 +0000 (17:07 +0200)
committerThomas Weißschuh <linux@weissschuh.net>
Mon, 6 Apr 2026 17:46:51 +0000 (19:46 +0200)
Add support for dynamically allocating formatted strings through
asprintf() and vasprintf().

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://patch.msgid.link/20260401-nolibc-asprintf-v1-3-46292313439f@weissschuh.net
tools/include/nolibc/stdio.h
tools/testing/selftests/nolibc/nolibc-test.c

index b6d14a58cfe720d6372783fa40497b8983a91294..ebdd413d13ec72ce60d25652863ea882b45837fe 100644 (file)
@@ -795,6 +795,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)
+{
+       int len1, len2;
+       char *buf;
+
+       len1 = vsnprintf(NULL, 0, fmt, args1);
+       if (len1 < 0)
+               return -1;
+
+       buf = malloc(len1 + 1);
+       if (!buf)
+               return -1;
+
+       len2 = vsnprintf(buf, len1 + 1, fmt, args2);
+       if (len2 < 0) {
+               free(buf);
+               return -1;
+       }
+
+       *strp = buf;
+       return len1;
+}
+
+static __attribute__((unused, format(printf, 2, 0)))
+int vasprintf(char **strp, const char *fmt, va_list args)
+{
+       va_list args2;
+       int ret;
+
+       va_copy(args2, args);
+       ret = __nolibc_vasprintf(strp, fmt, args, args2);
+       va_end(args2);
+
+       return ret;
+}
+
+static __attribute__((unused, format(printf, 2, 3)))
+int asprintf(char **strp, const char *fmt, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = vasprintf(strp, fmt, args);
+       va_end(args);
+
+       return ret;
+}
+
 static __attribute__((unused))
 int vsscanf(const char *str, const char *format, va_list args)
 {
index 7606a8b68d28b11f827453dc491abb59c8ad8754..91d95a1525682749d0fa0716ef5d3228aa5e452f 100644 (file)
@@ -1841,6 +1841,29 @@ static int test_printf_error(void)
        return 0;
 }
 
+int test_asprintf(void)
+{
+       char *str;
+       int ret;
+
+       ret = asprintf(&str, "foo%s", "bar");
+       if (ret == -1)
+               return 1;
+
+       if (ret != 6) {
+               free(str);
+               return 2;
+       }
+
+       if (memcmp(str, "foobar", 6) != 0) {
+               free(str);
+               return 3;
+       }
+
+       free(str);
+       return 0;
+}
+
 static int run_printf(int min, int max)
 {
        int test;
@@ -1904,6 +1927,7 @@ static int run_printf(int min, int max)
                CASE_TEST(errno-neg);    errno = -22; EXPECT_VFPRINTF(is_nolibc, "errno=-22   ", "%-12m"); break;
                CASE_TEST(scanf);        EXPECT_ZR(1, test_scanf()); break;
                CASE_TEST(printf_error); EXPECT_ZR(1, test_printf_error()); break;
+               CASE_TEST(asprintf);     EXPECT_ZR(1, test_asprintf()); break;
                case __LINE__:
                        return ret; /* must be last */
                /* note: do not set any defaults so as to permit holes above */