[vlc-devel] [PATCH 3/4] win32: make vlc_vsnprintf more like c99 vsnprintf

davidf+nntp at woaf.net davidf+nntp at woaf.net
Wed Apr 1 23:40:04 CEST 2009


From: David Flynn <davidf at rd.bbc.co.uk>

Fixes following issues using MSVCRT _snprintf:
 - Failure to null terminate all strings
 - Failure to return number of characters that would've been
   printed had the buffer been sufficiently large
 - Failure to accept size = 0 (and str = NULL) to determine
   final output length.

NB, the third issue above is fixed on *some* win32 implementations,
however it is not officially documented as being so.

Signed-off-by: David Flynn <davidf at rd.bbc.co.uk>
---
 include/vlc_fixups.h |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
index 6088eb5..6914daa 100644
--- a/include/vlc_fixups.h
+++ b/include/vlc_fixups.h
@@ -123,6 +123,7 @@ static inline int vlc_vsprintf (char *str, const char *format, va_list ap)
 }
 # define vsprintf vlc_vsprintf
 
+static inline int vasprintf (char **strp, const char *fmt, va_list ap);
 static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_list ap)
 {
     int must_free = vlc_fix_format_string (&format);
@@ -130,7 +131,18 @@ static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_
      * to 'aid' portability/standards compliance, mingw provides a
      * static version of vsnprintf that is buggy.  Be sure to use
      * MSVCRT version, at least it behaves as expected */
-    int ret = _vsnprintf (str, size, format, ap);
+    /* MSVCRT _vsnprintf does not:
+     *  - null terminate string if insufficient storage
+     *  - return the number of characters that would've been written
+     */
+    int ret = _vsnprintf (str, size-1, format, ap);
+    str[size-1] = 0; /* ensure the null gets written */
+    if (ret == -1)
+    {
+        /* work out the number of chars that should've been written */
+        ret = vasprintf (&str, format, ap);
+        if (ret >= 0 && str) free (str);
+    }
     if (must_free) free ((char *)format);
     return ret;
 }
@@ -195,7 +207,7 @@ static inline int vlc_snprintf (char *str, size_t size, const char *format, ...)
 # include <stdarg.h>
 static inline int vasprintf (char **strp, const char *fmt, va_list ap)
 {
-#ifndef UNDER_CE
+#ifndef WIN32
     int len = vsnprintf (NULL, 0, fmt, ap) + 1;
     char *res = (char *)malloc (len);
     if (res == NULL)
@@ -203,27 +215,31 @@ static inline int vasprintf (char **strp, const char *fmt, va_list ap)
     *strp = res;
     return vsnprintf (res, len, fmt, ap);
 #else
-    /* HACK: vsnprintf in the WinCE API behaves like
+    /* HACK: vsnprintf in the Win32 API behaves like
      * the one in glibc 2.0 and doesn't return the number of characters
      * it needed to copy the string.
      * cf http://msdn.microsoft.com/en-us/library/1kt27hek.aspx
      * and cf the man page of vsnprintf
-     *
-     Guess we need no more than 50 bytes. */
-    int n, size = 50;
+     */
+    int must_free = vlc_fix_format_string (&fmt);
+    int n, size = 2 * strlen (fmt);
     char *res, *np;
 
     if ((res = (char *) malloc (size)) == NULL)
+    {
+        if (must_free) free ((char *)fmt);
         return -1;
+    }
 
     while (1)
     {
-        n = vsnprintf (res, size, fmt, ap);
+        n = _vsnprintf (res, size, fmt, ap);
 
         /* If that worked, return the string. */
         if (n > -1 && n < size)
         {
             *strp = res;
+            if (must_free) free ((char *)fmt);
             return n;
         }
 
@@ -233,6 +249,7 @@ static inline int vasprintf (char **strp, const char *fmt, va_list ap)
         if ((np = (char *) realloc (res, size)) == NULL)
         {
             free(res);
+            if (must_free) free ((char *)fmt);
             return -1;
         }
         else
@@ -241,7 +258,7 @@ static inline int vasprintf (char **strp, const char *fmt, va_list ap)
         }
 
     }
-#endif /* UNDER_CE */
+#endif /* WIN32 */
 }
 #endif
 
-- 
1.5.6.5




More information about the vlc-devel mailing list