From: Thomas Weißschuh Date: Wed, 1 Apr 2026 15:07:29 +0000 (+0200) Subject: tools/nolibc: add support for asprintf() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=12496aad10c5671d66e160487326de942cd440ba;p=thirdparty%2Fkernel%2Flinux.git tools/nolibc: add support for asprintf() Add support for dynamically allocating formatted strings through asprintf() and vasprintf(). Signed-off-by: Thomas Weißschuh Acked-by: Willy Tarreau Link: https://patch.msgid.link/20260401-nolibc-asprintf-v1-3-46292313439f@weissschuh.net --- diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index b6d14a58cfe72..ebdd413d13ec7 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -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) { diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 7606a8b68d28b..91d95a1525682 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -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 */