msvc: Add snprintf/vsnprintf replacements
authorHenrik Gramner <henrik@gramner.com>
Mon, 11 Apr 2016 14:59:46 +0000 (16:59 +0200)
committerHenrik Gramner <henrik@gramner.com>
Mon, 11 Apr 2016 14:59:46 +0000 (16:59 +0200)
MSVC pre-VS2015 has broken snprintf/vsnprintf implementations which are
incompatible with C99 and may lead to buffer overflows.

common/osdep.c
common/osdep.h

index 074a1f3..81301f5 100644 (file)
@@ -168,4 +168,39 @@ int x264_is_pipe( const char *path )
     return 0;
 }
 #endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+/* MSVC pre-VS2015 has broken snprintf/vsnprintf implementations which are incompatible with C99. */
+int x264_snprintf( char *s, size_t n, const char *fmt, ... )
+{
+    va_list arg;
+    va_start( arg, fmt );
+    int length = x264_vsnprintf( s, n, fmt, arg );
+    va_end( arg );
+    return length;
+}
+
+int x264_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
+{
+    int length = -1;
+
+    if( n )
+    {
+        va_list arg2;
+        va_copy( arg2, arg );
+        length = _vsnprintf( s, n, fmt, arg2 );
+        va_end( arg2 );
+
+        /* _(v)snprintf adds a null-terminator only if the length is less than the buffer size. */
+        if( length < 0 || length >= n )
+            s[n-1] = '\0';
+    }
+
+    /* _(v)snprintf returns a negative number if the length is greater than the buffer size. */
+    if( length < 0 )
+        return _vscprintf( fmt, arg );
+
+    return length;
+}
+#endif
 #endif
index 995d03c..520710a 100644 (file)
 #define strtok_r strtok_s
 #define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
 #if _MSC_VER < 1900
-#define snprintf _snprintf
+int x264_snprintf( char *s, size_t n, const char *fmt, ... );
+int x264_vsnprintf( char *s, size_t n, const char *fmt, va_list arg );
+#define snprintf  x264_snprintf
+#define vsnprintf x264_vsnprintf
 #endif
 #endif