Commit 12496aad authored by Thomas Weißschuh's avatar Thomas Weißschuh
Browse files

tools/nolibc: add support for asprintf()



Add support for dynamically allocating formatted strings through
asprintf() and vasprintf().

Signed-off-by: default avatarThomas Weißschuh <linux@weissschuh.net>
Acked-by: default avatarWilly Tarreau <w@1wt.eu>
Link: https://patch.msgid.link/20260401-nolibc-asprintf-v1-3-46292313439f@weissschuh.net
parent fd2e9f82
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -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)
{
+24 −0
Original line number Diff line number Diff line
@@ -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 */