libwine: Make [v]snprintW() always null-terminate the buffer, even if it's short.

This commit is contained in:
Ken Thomases 2013-04-10 08:40:02 -05:00 committed by Alexandre Julliard
parent 822bcfdf74
commit 71377c5652
1 changed files with 39 additions and 28 deletions

View File

@ -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 )