From 7d183fbf5668de191ed45f221729c3cf906b49e8 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 28 Jul 2025 18:18:54 +0200 Subject: [PATCH 1/3] fix(utility): Fix edge case behavior of vsnprintf, vswprintf for VC6 builds --- Dependencies/Utility/Utility/stdio_adapter.h | 44 ++++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Dependencies/Utility/Utility/stdio_adapter.h b/Dependencies/Utility/Utility/stdio_adapter.h index bdee0600af7..f72f758c49c 100644 --- a/Dependencies/Utility/Utility/stdio_adapter.h +++ b/Dependencies/Utility/Utility/stdio_adapter.h @@ -26,38 +26,46 @@ inline int vsnprintf(char* _Buffer, size_t _BufferCount, const char* _Format, va_list _ArgList) { - // Microsoft's _vsnprintf does not null terminate when writing the entire length. - int result = _vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); - _Buffer[_BufferCount - 1] = '\0'; - return result; + // Microsoft's _vsnprintf does not null terminate when writing the entire length. + int result = _vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); + if (result == -1 || result == _BufferCount) + { + _Buffer[_BufferCount - 1] = '\0'; + return -1; + } + return result; } // Yes, this is called vswprintf instead of vsnwprintf inline int vswprintf(wchar_t* _Buffer, size_t _BufferCount, const wchar_t* _Format, va_list _ArgList) { - // Microsoft's _vsnwprintf does not null terminate when writing the entire length. - int result = _vsnwprintf(_Buffer, _BufferCount, _Format, _ArgList); - _Buffer[_BufferCount - 1] = L'\0'; - return result; + // Microsoft's _vsnwprintf does not null terminate when writing the entire length. + int result = _vsnwprintf(_Buffer, _BufferCount, _Format, _ArgList); + if (result == -1 || result == _BufferCount) + { + _Buffer[_BufferCount - 1] = L'\0'; + return -1; + } + return result; } inline int snprintf(char* _Buffer, size_t _BufferCount, const char* _Format, ...) { - va_list _ArgList; - va_start(_ArgList, _Format); - int result = vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); - va_end(_ArgList); - return result; + va_list _ArgList; + va_start(_ArgList, _Format); + int result = vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); + va_end(_ArgList); + return result; } // Yes, this is called swprintf instead of snwprintf inline int swprintf(wchar_t* _Buffer, size_t _BufferCount, const wchar_t* _Format, ...) { - va_list _ArgList; - va_start(_ArgList, _Format); - int result = vswprintf(_Buffer, _BufferCount, _Format, _ArgList); - va_end(_ArgList); - return result; + va_list _ArgList; + va_start(_ArgList, _Format); + int result = vswprintf(_Buffer, _BufferCount, _Format, _ArgList); + va_end(_ArgList); + return result; } #endif From 28f380ec9149f3fe6db9dc96c835dca9419a20b3 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Tue, 29 Jul 2025 18:00:32 +0200 Subject: [PATCH 2/3] Cast result to size_t --- Dependencies/Utility/Utility/stdio_adapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dependencies/Utility/Utility/stdio_adapter.h b/Dependencies/Utility/Utility/stdio_adapter.h index f72f758c49c..7c2415583ac 100644 --- a/Dependencies/Utility/Utility/stdio_adapter.h +++ b/Dependencies/Utility/Utility/stdio_adapter.h @@ -28,7 +28,7 @@ inline int vsnprintf(char* _Buffer, size_t _BufferCount, const char* _Format, va { // Microsoft's _vsnprintf does not null terminate when writing the entire length. int result = _vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); - if (result == -1 || result == _BufferCount) + if (result == -1 || (size_t)result == _BufferCount) { _Buffer[_BufferCount - 1] = '\0'; return -1; @@ -41,7 +41,7 @@ inline int vswprintf(wchar_t* _Buffer, size_t _BufferCount, const wchar_t* _Form { // Microsoft's _vsnwprintf does not null terminate when writing the entire length. int result = _vsnwprintf(_Buffer, _BufferCount, _Format, _ArgList); - if (result == -1 || result == _BufferCount) + if (result == -1 || (size_t)result == _BufferCount) { _Buffer[_BufferCount - 1] = L'\0'; return -1; From d64fa130142a51c0ced5427ee1eb8bf333bccd99 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Tue, 29 Jul 2025 18:05:47 +0200 Subject: [PATCH 3/3] Add null size check for buffer --- Dependencies/Utility/Utility/stdio_adapter.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dependencies/Utility/Utility/stdio_adapter.h b/Dependencies/Utility/Utility/stdio_adapter.h index 7c2415583ac..4228e081996 100644 --- a/Dependencies/Utility/Utility/stdio_adapter.h +++ b/Dependencies/Utility/Utility/stdio_adapter.h @@ -26,8 +26,11 @@ inline int vsnprintf(char* _Buffer, size_t _BufferCount, const char* _Format, va_list _ArgList) { + if (_BufferCount == 0) + return -1; // Microsoft's _vsnprintf does not null terminate when writing the entire length. int result = _vsnprintf(_Buffer, _BufferCount, _Format, _ArgList); + // Deal with errors and edge cases. if (result == -1 || (size_t)result == _BufferCount) { _Buffer[_BufferCount - 1] = '\0'; @@ -39,8 +42,11 @@ inline int vsnprintf(char* _Buffer, size_t _BufferCount, const char* _Format, va // Yes, this is called vswprintf instead of vsnwprintf inline int vswprintf(wchar_t* _Buffer, size_t _BufferCount, const wchar_t* _Format, va_list _ArgList) { + if (_BufferCount == 0) + return -1; // Microsoft's _vsnwprintf does not null terminate when writing the entire length. int result = _vsnwprintf(_Buffer, _BufferCount, _Format, _ArgList); + // Deal with errors and edge cases. if (result == -1 || (size_t)result == _BufferCount) { _Buffer[_BufferCount - 1] = L'\0';