diff options
author | Simon Howard | 2014-04-01 22:06:09 -0400 |
---|---|---|
committer | Simon Howard | 2014-04-01 22:06:09 -0400 |
commit | c30f4a2f65172a0d358e4c85c7d3270af13b829b (patch) | |
tree | 58b34414f340643c7a8ebca2641ff306889c6abd | |
parent | 007615bc247f51b8418cbdd62c2c8b8c74a7ee08 (diff) | |
download | chocolate-doom-c30f4a2f65172a0d358e4c85c7d3270af13b829b.tar.gz chocolate-doom-c30f4a2f65172a0d358e4c85c7d3270af13b829b.tar.bz2 chocolate-doom-c30f4a2f65172a0d358e4c85c7d3270af13b829b.zip |
misc: Fix safe vsnprintf() function.
An off-by-one error in the function caused the strings to be truncated
one character too early. Change the return value check so that
negative values are also interpreted as indicating truncation; this is
the behavior of the Win32 API.
-rw-r--r-- | src/m_misc.c | 15 | ||||
-rw-r--r-- | textscreen/txt_sdl.c | 15 |
2 files changed, 26 insertions, 4 deletions
diff --git a/src/m_misc.c b/src/m_misc.c index 4abd7ebf..d54e181e 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -459,6 +459,8 @@ char *M_StringJoin(const char *s, ...) // Safe, portable vsnprintf(). int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) { + int result; + if (buf_len < 1) { return 0; @@ -467,8 +469,17 @@ int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) // Windows (and other OSes?) has a vsnprintf() that doesn't always // append a trailing \0. So we must do it, and write into a buffer // that is one byte shorter; otherwise this function is unsafe. - buf[buf_len - 1] = '\0'; - return vsnprintf(buf, buf_len - 1, s, args); + result = vsnprintf(buf, buf_len, s, args); + + // If truncated, change the final char in the buffer to a \0. + // A negative result indicates a truncated buffer on Windows. + if (result < 0 || result >= buf_len) + { + buf[buf_len - 1] = '\0'; + result = buf_len - 1; + } + + return result; } // Safe, portable snprintf(). diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c index 860adfa6..984a2e75 100644 --- a/textscreen/txt_sdl.c +++ b/textscreen/txt_sdl.c @@ -906,6 +906,8 @@ void TXT_StringConcat(char *dest, const char *src, size_t dest_len) // Safe, portable vsnprintf(). int TXT_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) { + int result; + if (buf_len < 1) { return 0; @@ -914,8 +916,17 @@ int TXT_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) // Windows (and other OSes?) has a vsnprintf() that doesn't always // append a trailing \0. So we must do it, and write into a buffer // that is one byte shorter; otherwise this function is unsafe. - buf[buf_len - 1] = '\0'; - return vsnprintf(buf, buf_len - 1, s, args); + result = vsnprintf(buf, buf_len, s, args); + + // If truncated, change the final char in the buffer to a \0. + // A negative result indicates a truncated buffer on Windows. + if (result < 0 || result >= buf_len) + { + buf[buf_len - 1] = '\0'; + result = buf_len - 1; + } + + return result; } // Safe, portable snprintf(). |