Commit 3779d5bd authored by David Flynn's avatar David Flynn Committed by Jean-Baptiste Kempf

win32: vlc_fix_format_string - various fixes

- avoid mingw problems with %l*
- avoid using %I32 on Win32, since wince doesn't support it
- unify WIN64 and WIN32 cases.
- if malloc were to fail(!), don't allow unfiltered format string
  to get passed to *printf.
  (substitues an error message)
Signed-off-by: default avatarDavid Flynn <davidf@rd.bbc.co.uk>
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 151982aa
...@@ -39,56 +39,58 @@ static inline char *strdup (const char *str) ...@@ -39,56 +39,58 @@ static inline char *strdup (const char *str)
#endif #endif
#ifdef WIN32 #ifdef WIN32
/* Windows' printf doesn't support %z modifiers, thus we need to rewrite
* the format string in a wrapper. */
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
static inline char *vlc_fix_format_string (const char *format) /**
* vlc_fix_format_string:
* @format: address of format string to fix (format string is not modified)
*
* Windows' printf doesn't support %z size modifiers.
* Fix a *printf format string to make it safe for mingw/MSVCRT run times:
* %z* (not supported in MSVCRT) -> either %I64* or %I32.
*
* Returns: 1 if *format must be free()d; 0 otherwise
*/
static inline int vlc_fix_format_string (const char **format)
{ {
char *fmt; int n = 0;
# ifdef WIN64 const char *tmp = *format;
const char *src = format, *tmp; while ((tmp = strstr (tmp, "%z")) != NULL)
char *dst;
size_t n = 0;
while ((tmp = strstr (src, "%z")) != NULL)
{ {
n++; n++;
src = tmp + 2; tmp += 2;
} }
if (n == 0) if (!n)
return NULL; return 0;
fmt = (char*)malloc (strlen (format) + n + 1); char *dst = (char*)malloc (strlen (*format) + 2*n + 1);
if (fmt == NULL) if (!dst)
return NULL; {
*format = "vlc_fix_format_string: due to malloc failure, unable to fix unsafe string";
return 0;
}
src = format; const char *src = *format;
dst = fmt; *format = dst;
while ((tmp = strstr (src, "%z")) != NULL) while ((tmp = strstr (src, "%z")) != NULL)
{ {
/* NB, don't use %l*, as this is buggy in mingw*/
size_t d = tmp - src; size_t d = tmp - src;
memcpy (dst, src, d); memcpy (dst, src, d);
dst += d; dst += d;
memcpy (dst, "%ll", 3); *dst++ = '%';
dst += 3; # ifdef WIN64
*dst++ = 'I';
*dst++ = '6';
*dst++ = '4';
# else /* ie: WIN32 */
/* on win32, since the default size is 32bit, dont specify
* a modifer. (I32 isn't on wince, l doesn't work on mingw) */
# endif
src = tmp + 2; src = tmp + 2;
} }
strcpy (dst, src); strcpy (dst, src);
# else return 1;
char *f;
if (strstr (format, "%z") == NULL)
return NULL;
fmt = strdup (format);
if (fmt == NULL)
return NULL;
while ((f = strstr (fmt, "%z")) != NULL)
{
f[1] = 'l';
}
# endif
return fmt;
} }
# include <stdio.h> # include <stdio.h>
...@@ -96,40 +98,40 @@ static inline char *vlc_fix_format_string (const char *format) ...@@ -96,40 +98,40 @@ static inline char *vlc_fix_format_string (const char *format)
static inline int vlc_vprintf (const char *format, va_list ap) static inline int vlc_vprintf (const char *format, va_list ap)
{ {
char *fmt = vlc_fix_format_string (format); int must_free = vlc_fix_format_string (&format);
int ret = vprintf (fmt ? fmt : format, ap); int ret = vprintf (format, ap);
free (fmt); if (must_free) free ((char *)format);
return ret; return ret;
} }
# define vprintf vlc_vprintf # define vprintf vlc_vprintf
static inline int vlc_vfprintf (FILE *stream, const char *format, va_list ap) static inline int vlc_vfprintf (FILE *stream, const char *format, va_list ap)
{ {
char *fmt = vlc_fix_format_string (format); int must_free = vlc_fix_format_string (&format);
int ret = vfprintf (stream, fmt ? fmt : format, ap); int ret = vfprintf (stream, format, ap);
free (fmt); if (must_free) free ((char *)format);
return ret; return ret;
} }
# define vfprintf vlc_vfprintf # define vfprintf vlc_vfprintf
static inline int vlc_vsprintf (char *str, const char *format, va_list ap) static inline int vlc_vsprintf (char *str, const char *format, va_list ap)
{ {
char *fmt = vlc_fix_format_string (format); int must_free = vlc_fix_format_string (&format);
int ret = vsprintf (str, fmt ? fmt : format, ap); int ret = vsprintf (str, format, ap);
free (fmt); if (must_free) free ((char *)format);
return ret; return ret;
} }
# define vsprintf vlc_vsprintf # define vsprintf vlc_vsprintf
static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_list ap) static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_list ap)
{ {
char *fmt = vlc_fix_format_string (format); int must_free = vlc_fix_format_string (&format);
/* traditionally, MSVCRT has provided vsnprintf as _vsnprintf; /* traditionally, MSVCRT has provided vsnprintf as _vsnprintf;
* to 'aid' portability/standards compliance, mingw provides a * to 'aid' portability/standards compliance, mingw provides a
* static version of vsnprintf that is buggy. Be sure to use * static version of vsnprintf that is buggy. Be sure to use
* MSVCRT version, at least it behaves as expected */ * MSVCRT version, at least it behaves as expected */
int ret = _vsnprintf (str, size, fmt ? fmt : format, ap); int ret = _vsnprintf (str, size, format, ap);
free (fmt); if (must_free) free ((char *)format);
return ret; return ret;
} }
# define vsnprintf vlc_vsnprintf # define vsnprintf vlc_vsnprintf
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment