[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