shithub: choc

Download patch

ref: c30f4a2f65172a0d358e4c85c7d3270af13b829b
parent: 007615bc247f51b8418cbdd62c2c8b8c74a7ee08
author: Simon Howard <fraggle@gmail.com>
date: Tue Apr 1 18:06:09 EDT 2014

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.

--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -459,6 +459,8 @@
 // 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 @@
     // 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().
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -906,6 +906,8 @@
 // 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 @@
     // 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().