include: vsnprintf should always write a null terminator.
Microsoft's documentation says:
The
vsnprintf
function always writes a null terminator, even if it truncates the output. When you use_vsnprintf
and_vsnwprintf
, the buffer is null-terminated only if there's room at the end (that is, if the number of characters to write is less than count).
For _UCRT
and _MSVCR_VER >= 140
, vsnprintf
calls __stdio_common_vsprintf
with _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
, and everything works, a null byte is appended, everything is fine.
If not, vsnprintf
calls _vsnprintf
directly and no null byte will be added if the buffer is not big enough. This happens in, for example, kernel32. And this breaks wine_dbg_vsprintf
, which passes result of vsnprintf
to strlen
and goes out-of-bound.
In msvcrt.spec, we also have vsnprintf
as an alias of _vsnprintf
, I didn't touch that since I don't know if that's deliberate. But this alias is used (by e.g. winecrt0, i think?), if this one is also wrong then it might break other things.