From b7cdb29a07d98f06af320b7dd0cfb61329f6adbc Mon Sep 17 00:00:00 2001 From: Yunlk <3283559503@qq.com> Date: Fri, 30 Oct 2026 11:53:11 +0800 Subject: [PATCH] [klibc] fix: rt_sprintf() writes nothing when libc vsnprintf is used rt_vsprintf() passed (size_t)-1 as the buffer size to rt_vsnprintf(). That is harmless for the built-in implementation, which only uses the size to stop writing, but with RT_KLIBC_USING_LIBC_VSNPRINTF the call is forwarded to libc: rt_sprintf() -> rt_vsprintf() -> rt_vsnprintf(buf, SIZE_MAX, ...) -> vsnprintf() libc derives the end of the buffer from buf + size, and 0xFFFFFFFFFFFFFFFF overflows on 64-bit targets, so the call fails without writing a single byte: rt_snprintf(buf, 100, "%d", 42) -> ret=2 buf="42" rt_sprintf(buf, "%d", 42) -> ret=-1 buf=0xCC (untouched) This is what makes core.klibc.rt_sprintf fail on qemu-virt64-aarch64 when RT_KLIBC_USING_LIBC_VSNPRINTF is enabled: every SPRINTF_CHECK() compares the 0xCC filled buffer against the expected string. Delegate to libc's vsprintf() instead, which takes no size argument and is the exact counterpart of what rt_vsprintf() has to do. Verified on bsp/qemu-virt64-aarch64 with RT_UTEST_TC_USING_KLIBC + CI_ACTION: RT_KLIBC_USING_LIBC_VSNPRINTF=y before: core.klibc.rt_sprintf FAILED, 5 other klibc cases passed after : all 6 klibc cases PASSED RT_KLIBC_USING_LIBC_VSNPRINTF not set (built-in rt_vsnprintf path) after : all 6 klibc cases PASSED Refs #10027 --- src/klibc/kstdio.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/klibc/kstdio.c b/src/klibc/kstdio.c index 257b1ff1a819..0fc52858a786 100644 --- a/src/klibc/kstdio.c +++ b/src/klibc/kstdio.c @@ -51,7 +51,18 @@ RTM_EXPORT(rt_snprintf); */ int rt_vsprintf(char *buf, const char *format, va_list arg_ptr) { +#ifdef RT_KLIBC_USING_LIBC_VSNPRINTF + /* + * rt_vsnprintf() delegates to libc here. Passing (size_t)-1 to it is not + * safe: libc computes the end of the buffer as buf + size, which overflows + * on 64-bit targets, and the call then fails without writing anything + * (rt_sprintf() returned -1 and left the buffer untouched). libc has + * vsprintf() for exactly this case. + */ + return vsprintf(buf, format, arg_ptr); +#else return rt_vsnprintf(buf, (size_t) - 1, format, arg_ptr); +#endif } RTM_EXPORT(rt_vsprintf);