Ken Thomases : libwine: Make [v]snprintW() always null-terminate the buffer , even if it's short.
Alexandre Julliard
julliard at winehq.org
Wed Apr 10 14:16:16 CDT 2013
Module: wine
Branch: master
Commit: 71377c5652a2125b46ea7ad8651f73c1852a0083
URL: http://source.winehq.org/git/wine.git/?a=commit;h=71377c5652a2125b46ea7ad8651f73c1852a0083
Author: Ken Thomases <ken at codeweavers.com>
Date: Wed Apr 10 08:40:02 2013 -0500
libwine: Make [v]snprintW() always null-terminate the buffer, even if it's short.
---
libs/wine/string.c | 67 ++++++++++++++++++++++++++++++---------------------
1 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/libs/wine/string.c b/libs/wine/string.c
index 0b42ea8..f2a9bd3 100644
--- a/libs/wine/string.c
+++ b/libs/wine/string.c
@@ -300,7 +300,7 @@ noconv:
/* 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;
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 ((count += width - max) >= len) return -1;
- for (i = 0; i < width - max; i++) *buffer++ = ' ';
+ for (i = 0; i < width - max; i++)
+ {
+ if (count++ < len)
+ *buffer++ = ' ';
+ }
}
- if ((count += max) >= len) return -1;
- memcpy( buffer, str, max * sizeof(WCHAR) );
+ if (count < len)
+ memcpy( buffer, str, min( max, len - count ) * sizeof(WCHAR) );
+ count += max;
buffer += max;
if (left_align && width > max)
{
- if ((count += width - max) >= len) return -1;
- for (i = 0; i < width - max; i++) *buffer++ = ' ';
+ for (i = 0; i < width - max; i++)
+ {
+ if (count++ < len)
+ *buffer++ = ' ';
+ }
}
return count;
}
@@ -357,17 +364,16 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
{
while (*iter && *iter != '%')
{
- if (written++ >= len)
- return -1;
- *str++ = *iter++;
+ if (written++ < len)
+ *str++ = *iter;
+ iter++;
}
if (*iter == '%')
{
if (iter[1] == '%')
{
- if (written++ >= len)
- return -1;
- *str++ = '%'; /* "%%"->'%' */
+ if (written++ < len)
+ *str++ = '%'; /* "%%"->'%' */
iter += 2;
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 };
const WCHAR *wstr = va_arg(valist, const WCHAR *);
- int count;
+ size_t remaining = written < len ? len - written : 0;
+ size_t count;
*fmta++ = 's';
*fmta = 0;
- count = format_string( str, len - written, fmtbufa, wstr ? wstr : none, -1 );
- if (count == -1) return -1;
- str += count;
+ count = format_string( str, remaining, fmtbufa, wstr ? wstr : none, -1 );
+ str += min( count, remaining );
written += count;
iter++;
break;
@@ -437,14 +443,14 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
case 'c':
{
WCHAR wstr;
- int count;
+ size_t remaining = written < len ? len - written : 0;
+ size_t count;
wstr = va_arg(valist, int);
*fmta++ = 's';
*fmta = 0;
- count = format_string( str, len - written, fmtbufa, &wstr, 1 );
- if (count == -1) return -1;
- str += count;
+ count = format_string( str, remaining, fmtbufa, &wstr, 1 );
+ str += min( count, remaining );
written += count;
iter++;
break;
@@ -475,9 +481,9 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
}
while (*bufaiter)
{
- if (written++ >= len)
- return -1;
- *str++ = *bufaiter++;
+ if (written++ < len)
+ *str++ = *bufaiter;
+ bufaiter++;
}
iter++;
break;
@@ -485,10 +491,15 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
}
}
}
- if (written >= len)
- return -1;
- *str++ = 0;
- return (int)written;
+ if (len)
+ {
+ if (written >= len)
+ 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 )
More information about the wine-cvs
mailing list