Skip to content

Commit 077bf73

Browse files
committed
fix: resolve vsnprintf(NULL, 0) crashes on older MSVC toolchains
- Removed native _vsnprintf(NULL, 0) mock logic which crashed on older MSVC environments by invoking the invalid parameter handler. - Updated allback_vsnprintf and test mocks to gracefully delegate null sizing calls to _vscprintf across all _WIN32 platforms. - Applied uniform clang-format guards over header include blocks. - Ensured robust C89 compliance without disabling compiler warnings.
1 parent b67e102 commit 077bf73

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

‎c89stringutils/c89stringutils_string_extras.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,14 @@ static int fallback_vsnprintf(char *buffer, size_t count, const char *format,
272272
#if defined(C89STRINGUTILS_HAVE_VSNPRINTF)
273273
rc = vsnprintf(NULL, 0, format, args);
274274
#elif defined(C89STRINGUTILS_HAVE__VSNPRINTF)
275+
#if !defined(_MSC_VER)
275276
rc = _vsnprintf(NULL, 0, format, args);
277+
#else
278+
/* _vsnprintf(NULL, 0) crashes on older MSVC by invoking the invalid
279+
parameter handler. If _vscprintf is not available, we should fallback to
280+
a safe mechanism or return -1. */
281+
rc = -1;
282+
#endif
276283
#endif
277284
#endif
278285
if (rc < 0) {
@@ -623,6 +630,11 @@ C89STRINGUTILS_EXPORT int c89stringutils_vsnprintf_s(char *s, rsize_t n,
623630
#endif
624631
C89STRINGUTILS_EXPORT int
625632
c89stringutils_vsnprintf(char *s, size_t n, const char *format, va_list arg) {
633+
#if defined(_WIN32)
634+
if (s == NULL || n == 0) {
635+
return fallback_vsnprintf(s, n, format, arg);
636+
}
637+
#endif
626638
#if defined(C89STRINGUTILS_HAVE_VSNPRINTF)
627639
return vsnprintf(s, n, format, arg);
628640
#elif defined(C89STRINGUTILS_HAVE__VSNPRINTF)

‎c89stringutils/tests/test.c‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,9 @@ int mock_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
135135
if (str == NULL) {
136136
/* Need a valid buffer for vsprintf if vsnprintf is missing, but cygwin has
137137
* vsnprintf */
138-
#if defined(_MSC_VER)
138+
#if defined(_WIN32)
139139
ret = _vscprintf(format, ap);
140-
#elif defined(__CYGWIN__) || defined(__linux__) || defined(__APPLE__) || \
141-
defined(_WIN32)
140+
#elif defined(__CYGWIN__) || defined(__linux__) || defined(__APPLE__)
142141
ret = vsnprintf(NULL, 0, format, ap);
143142
#else
144143
char dummy[1024];
@@ -165,7 +164,7 @@ int mock_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
165164
*/
166165
int mock_vscprintf(const char *format, va_list ap) {
167166
int ret = -1;
168-
#ifdef _MSC_VER
167+
#if defined(_WIN32)
169168
ret = _vscprintf(format, ap);
170169
#else
171170
ret = vsnprintf(NULL, 0, format, ap);

0 commit comments

Comments
 (0)