From 1c7e3f100f4ff51be2ac85a1d21d2b6f2926ea39 Mon Sep 17 00:00:00 2001 From: Erik de Castro Lopo Date: Mon, 22 Sep 2014 18:29:32 +1000 Subject: [PATCH] Windows specific vsnprintf fixes. * Changes flac_snprintf (in src/share/grabbag/snprintf.c) and its copy local_snprintf (src/libFLAC/metadata_iterators.c) to be almost sane. * Adds flac_vsnprintf (src/share/grabbag/snprintf.c) and its copy local_vsnprintf (src/share/win_utf8_io/win_utf8_io.c). * Changes stats_print_info in src/flac/utils.c so it uses flac_vsnprintf instead of vsnprintf. This makes return value checking unnecessary. Patch-from: lvqcl --- include/share/compat.h | 2 ++ src/flac/utils.c | 6 +----- src/libFLAC/metadata_iterators.c | 11 ++++++++--- src/share/grabbag/snprintf.c | 33 +++++++++++++++++++++++++++++---- src/share/win_utf8_io/win_utf8_io.c | 34 ++++++++++++++++++++++++++++------ 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/include/share/compat.h b/include/share/compat.h index 3ae9d8d4..db5f7ca2 100644 --- a/include/share/compat.h +++ b/include/share/compat.h @@ -188,10 +188,12 @@ * * This function wraps the MS version to behave more like the the ISO version. */ +#include #ifdef __cplusplus extern "C" { #endif int flac_snprintf(char *str, size_t size, const char *fmt, ...); +int flac_vsnprintf(char *str, size_t size, const char *fmt, va_list va); #ifdef __cplusplus }; #endif diff --git a/src/flac/utils.c b/src/flac/utils.c index d0102b41..59dd845f 100644 --- a/src/flac/utils.c +++ b/src/flac/utils.c @@ -247,12 +247,8 @@ void stats_print_info(int level, const char *format, ...) if (flac__utils_verbosity_ >= level) { va_list args; va_start(args, format); - len = vsnprintf(tmp, sizeof(tmp), format, args); + len = flac_vsnprintf(tmp, sizeof(tmp), format, args); va_end(args); - if (len < 0 || len == sizeof(tmp)) { - tmp[sizeof(tmp)-1] = '\0'; - len = sizeof(tmp)-1; - } stats_clear(); if (len >= console_chars_left) { clear_len = console_chars_left; diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c index 778bb8c6..d50df39e 100644 --- a/src/libFLAC/metadata_iterators.c +++ b/src/libFLAC/metadata_iterators.c @@ -3201,13 +3201,18 @@ static int local_snprintf(char *str, size_t size, const char *fmt, ...) { va_list va; - int rc ; + int rc; va_start (va, fmt); -#ifdef _MSC_VER +#if defined _MSC_VER + if (size == 0) + return 1024; rc = vsnprintf_s (str, size, _TRUNCATE, fmt, va); - rc = (rc > 0) ? rc : (size == 0 ? 1024 : size * 2); + if (rc < 0) + rc = size - 1; +#elif defined __MINGW32__ + rc = __mingw_vsnprintf (str, size, fmt, va); #else rc = vsnprintf (str, size, fmt, va); #endif diff --git a/src/share/grabbag/snprintf.c b/src/share/grabbag/snprintf.c index 3a0661f0..d19e42c1 100644 --- a/src/share/grabbag/snprintf.c +++ b/src/share/grabbag/snprintf.c @@ -49,7 +49,7 @@ * does not over-write the end of the buffer. MS's snprintf_s in this case * returns -1. * - * The _MSC_VER code below attempts to modify the return code for snprintf_s + * The _MSC_VER code below attempts to modify the return code for vsnprintf_s * to something that is more compatible with the behaviour of the ISO C version. */ @@ -57,13 +57,18 @@ int flac_snprintf(char *str, size_t size, const char *fmt, ...) { va_list va; - int rc ; + int rc; va_start (va, fmt); -#ifdef _MSC_VER +#if defined _MSC_VER + if (size == 0) + return 1024; rc = vsnprintf_s (str, size, _TRUNCATE, fmt, va); - rc = (rc > 0) ? rc : (size == 0 ? 1024 : size * 2); + if (rc < 0) + rc = size - 1; +#elif defined __MINGW32__ + rc = __mingw_vsnprintf (str, size, fmt, va); #else rc = vsnprintf (str, size, fmt, va); #endif @@ -71,3 +76,23 @@ flac_snprintf(char *str, size_t size, const char *fmt, ...) return rc; } + +int +flac_vsnprintf(char *str, size_t size, const char *fmt, va_list va) +{ + int rc; + +#if defined _MSC_VER + if (size == 0) + return 1024; + rc = vsnprintf_s (str, size, _TRUNCATE, fmt, va); + if (rc < 0) + rc = size - 1; +#elif defined __MINGW32__ + rc = __mingw_vsnprintf (str, size, fmt, va); +#else + rc = vsnprintf (str, size, fmt, va); +#endif + + return rc; +} diff --git a/src/share/win_utf8_io/win_utf8_io.c b/src/share/win_utf8_io/win_utf8_io.c index 31b44431..d7a2d099 100644 --- a/src/share/win_utf8_io/win_utf8_io.c +++ b/src/share/win_utf8_io/win_utf8_io.c @@ -45,6 +45,28 @@ #include "share/win_utf8_io.h" +#define UTF8_BUFFER_SIZE 32768 + +static +int local_vsnprintf(char *str, size_t size, const char *fmt, va_list va) +{ + int rc; + +#if defined _MSC_VER + if (size == 0) + return 1024; + rc = vsnprintf_s (str, size, _TRUNCATE, fmt, va); + if (rc < 0) + rc = size - 1; +#elif defined __MINGW32__ + rc = __mingw_vsnprintf (str, size, fmt, va); +#else + rc = vsnprintf (str, size, fmt, va); +#endif + + return rc; +} + static UINT win_utf8_io_codepage = CP_ACP; /* convert WCHAR stored Unicode string to UTF-8. Caller is responsible for freeing memory */ @@ -177,9 +199,9 @@ int printf_utf8(const char *format, ...) while (1) { va_list argptr; - if (!(utmp = (char *)malloc(32768*sizeof(char)))) break; + if (!(utmp = (char *)malloc(UTF8_BUFFER_SIZE*sizeof(char)))) break; va_start(argptr, format); - ret = vsnprintf_s(utmp, 32768, _TRUNCATE, format, argptr); + ret = local_vsnprintf(utmp, UTF8_BUFFER_SIZE, format, argptr); va_end(argptr); if (ret < 0) break; if (!(wout = wchar_from_utf8(utmp))) { @@ -203,9 +225,9 @@ int fprintf_utf8(FILE *stream, const char *format, ...) while (1) { va_list argptr; - if (!(utmp = (char *)malloc(32768*sizeof(char)))) break; + if (!(utmp = (char *)malloc(UTF8_BUFFER_SIZE*sizeof(char)))) break; va_start(argptr, format); - ret = vsnprintf_s(utmp, 32768, _TRUNCATE, format, argptr); + ret = local_vsnprintf(utmp, UTF8_BUFFER_SIZE, format, argptr); va_end(argptr); if (ret < 0) break; if (!(wout = wchar_from_utf8(utmp))) { @@ -228,8 +250,8 @@ int vfprintf_utf8(FILE *stream, const char *format, va_list argptr) int ret = -1; while (1) { - if (!(utmp = (char *)malloc(32768*sizeof(char)))) break; - if ((ret = vsnprintf_s(utmp, 32768, _TRUNCATE, format, argptr)) < 0) break; + if (!(utmp = (char *)malloc(UTF8_BUFFER_SIZE*sizeof(char)))) break; + if ((ret = local_vsnprintf(utmp, UTF8_BUFFER_SIZE, format, argptr)) < 0) break; if (!(wout = wchar_from_utf8(utmp))) { ret = -1; break; -- 2.11.4.GIT