Ken Thomases : libwine: Make [v]snprintW() always null-terminate the buffer , even if it's short.
Module: wine Branch: master Commit: 71377c5652a2125b46ea7ad8651f73c1852a0083 URL: http://source.winehq.org/git/wine.git/?a=commit;h=71377c5652a2125b46ea7ad865... Author: Ken Thomases <ken(a)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 )
participants (1)
-
Alexandre Julliard