libwine: Make [v]snprintW() always null-terminate the buffer, even if it's short.
This commit is contained in:
parent
822bcfdf74
commit
71377c5652
|
@ -300,7 +300,7 @@ noconv:
|
||||||
|
|
||||||
|
|
||||||
/* format a WCHAR string according to a printf format; helper for vsnprintfW */
|
/* format a WCHAR string according to a printf format; helper for vsnprintfW */
|
||||||
static int format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
|
static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
int i, left_align = 0, width = 0, max = 0;
|
int i, left_align = 0, width = 0, max = 0;
|
||||||
|
@ -331,18 +331,25 @@ static int format_string( WCHAR *buffer, size_t len, const char *format, const W
|
||||||
|
|
||||||
if (!left_align && width > max)
|
if (!left_align && width > max)
|
||||||
{
|
{
|
||||||
if ((count += width - max) >= len) return -1;
|
for (i = 0; i < width - max; i++)
|
||||||
for (i = 0; i < width - max; i++) *buffer++ = ' ';
|
{
|
||||||
|
if (count++ < len)
|
||||||
|
*buffer++ = ' ';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((count += max) >= len) return -1;
|
if (count < len)
|
||||||
memcpy( buffer, str, max * sizeof(WCHAR) );
|
memcpy( buffer, str, min( max, len - count ) * sizeof(WCHAR) );
|
||||||
|
count += max;
|
||||||
buffer += max;
|
buffer += max;
|
||||||
|
|
||||||
if (left_align && width > max)
|
if (left_align && width > max)
|
||||||
{
|
{
|
||||||
if ((count += width - max) >= len) return -1;
|
for (i = 0; i < width - max; i++)
|
||||||
for (i = 0; i < width - max; i++) *buffer++ = ' ';
|
{
|
||||||
|
if (count++ < len)
|
||||||
|
*buffer++ = ' ';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -357,17 +364,16 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
|
||||||
{
|
{
|
||||||
while (*iter && *iter != '%')
|
while (*iter && *iter != '%')
|
||||||
{
|
{
|
||||||
if (written++ >= len)
|
if (written++ < len)
|
||||||
return -1;
|
*str++ = *iter;
|
||||||
*str++ = *iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
if (*iter == '%')
|
if (*iter == '%')
|
||||||
{
|
{
|
||||||
if (iter[1] == '%')
|
if (iter[1] == '%')
|
||||||
{
|
{
|
||||||
if (written++ >= len)
|
if (written++ < len)
|
||||||
return -1;
|
*str++ = '%'; /* "%%"->'%' */
|
||||||
*str++ = '%'; /* "%%"->'%' */
|
|
||||||
iter += 2;
|
iter += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -422,13 +428,13 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
|
||||||
{
|
{
|
||||||
static const WCHAR none[] = { '(','n','u','l','l',')',0 };
|
static const WCHAR none[] = { '(','n','u','l','l',')',0 };
|
||||||
const WCHAR *wstr = va_arg(valist, const WCHAR *);
|
const WCHAR *wstr = va_arg(valist, const WCHAR *);
|
||||||
int count;
|
size_t remaining = written < len ? len - written : 0;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
*fmta++ = 's';
|
*fmta++ = 's';
|
||||||
*fmta = 0;
|
*fmta = 0;
|
||||||
count = format_string( str, len - written, fmtbufa, wstr ? wstr : none, -1 );
|
count = format_string( str, remaining, fmtbufa, wstr ? wstr : none, -1 );
|
||||||
if (count == -1) return -1;
|
str += min( count, remaining );
|
||||||
str += count;
|
|
||||||
written += count;
|
written += count;
|
||||||
iter++;
|
iter++;
|
||||||
break;
|
break;
|
||||||
|
@ -437,14 +443,14 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
|
||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
WCHAR wstr;
|
WCHAR wstr;
|
||||||
int count;
|
size_t remaining = written < len ? len - written : 0;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
wstr = va_arg(valist, int);
|
wstr = va_arg(valist, int);
|
||||||
*fmta++ = 's';
|
*fmta++ = 's';
|
||||||
*fmta = 0;
|
*fmta = 0;
|
||||||
count = format_string( str, len - written, fmtbufa, &wstr, 1 );
|
count = format_string( str, remaining, fmtbufa, &wstr, 1 );
|
||||||
if (count == -1) return -1;
|
str += min( count, remaining );
|
||||||
str += count;
|
|
||||||
written += count;
|
written += count;
|
||||||
iter++;
|
iter++;
|
||||||
break;
|
break;
|
||||||
|
@ -475,9 +481,9 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
|
||||||
}
|
}
|
||||||
while (*bufaiter)
|
while (*bufaiter)
|
||||||
{
|
{
|
||||||
if (written++ >= len)
|
if (written++ < len)
|
||||||
return -1;
|
*str++ = *bufaiter;
|
||||||
*str++ = *bufaiter++;
|
bufaiter++;
|
||||||
}
|
}
|
||||||
iter++;
|
iter++;
|
||||||
break;
|
break;
|
||||||
|
@ -485,10 +491,15 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (written >= len)
|
if (len)
|
||||||
return -1;
|
{
|
||||||
*str++ = 0;
|
if (written >= len)
|
||||||
return (int)written;
|
str--;
|
||||||
|
*str++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: POSIX [v]snprintf() returns the equivalent of written, not -1, on short buffer. */
|
||||||
|
return written < len ? (int)written : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
|
int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
|
||||||
|
|
Loading…
Reference in New Issue