msvcrt: Estimate required buffer size better in pf_vsnprintf.

This commit is contained in:
Jesse Allen 2006-11-13 20:55:02 -07:00 committed by Alexandre Julliard
parent fa8656f841
commit 5b75c86921
1 changed files with 33 additions and 9 deletions

View File

@ -281,6 +281,7 @@ static inline int pf_output_stringA( pf_output *out, LPCSTR str, int len )
return -1; return -1;
} }
/* pf_fill: takes care of signs, alignment, zero and field padding */
static inline int pf_fill( pf_output *out, int len, pf_flags *flags, char left ) static inline int pf_fill( pf_output *out, int len, pf_flags *flags, char left )
{ {
int i, r = 0; int i, r = 0;
@ -426,15 +427,19 @@ static void pf_rebuild_format_string( char *p, pf_flags *flags )
*p++ = 0; *p++ = 0;
} }
/* pf_integer_conv: prints x to buf, including alternate formats, /* pf_integer_conv: prints x to buf, including alternate formats and
but not the sign */ additional precision digits, but not field characters or the sign */
static void pf_integer_conv( char *buf, pf_flags *flags, LONGLONG x ) static void pf_integer_conv( char *buf, int buf_len, pf_flags *flags,
LONGLONG x )
{ {
unsigned int base; unsigned int base;
const char *digits; const char *digits;
int i, j, k; int i, j, k;
char tmp[40]; char number[40], *tmp = number;
if( buf_len > sizeof number )
tmp = HeapAlloc( GetProcessHeap(), 0, buf_len );
base = 10; base = 10;
if( flags->Format == 'o' ) if( flags->Format == 'o' )
@ -487,6 +492,9 @@ static void pf_integer_conv( char *buf, pf_flags *flags, LONGLONG x )
/* Adjust precision so pf_fill won't truncate the number later */ /* Adjust precision so pf_fill won't truncate the number later */
flags->Precision = strlen( buf ); flags->Precision = strlen( buf );
if( tmp != number )
HeapFree( GetProcessHeap(), 0, tmp );
return; return;
} }
@ -660,10 +668,18 @@ static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist )
{ {
char number[40], *x = number; char number[40], *x = number;
if( flags.FieldLength >= sizeof number ) /* Estimate largest possible required buffer size:
x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 ); * Chooses the larger of the field or precision
* Includes extra bytes: 1 byte for null, 1 byte for sign,
4 bytes for exponent, 2 bytes for alternate formats, 1 byte
for a decimal, and 1 byte for an additional float digit. */
int x_len = ((flags.FieldLength > flags.Precision) ?
flags.FieldLength : flags.Precision) + 10;
pf_integer_conv( x, &flags, va_arg(valist, LONGLONG) ); if( x_len >= sizeof number)
x = HeapAlloc( GetProcessHeap(), 0, x_len );
pf_integer_conv( x, x_len, &flags, va_arg(valist, LONGLONG) );
r = pf_output_format_A( out, x, -1, &flags ); r = pf_output_format_A( out, x, -1, &flags );
if( x != number ) if( x != number )
@ -675,8 +691,16 @@ static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist )
{ {
char fmt[20], number[40], *x = number; char fmt[20], number[40], *x = number;
if( flags.FieldLength >= sizeof number ) /* Estimate largest possible required buffer size:
x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 ); * Chooses the larger of the field or precision
* Includes extra bytes: 1 byte for null, 1 byte for sign,
4 bytes for exponent, 2 bytes for alternate formats, 1 byte
for a decimal, and 1 byte for an additional float digit. */
int x_len = ((flags.FieldLength > flags.Precision) ?
flags.FieldLength : flags.Precision) + 10;
if( x_len >= sizeof number)
x = HeapAlloc( GetProcessHeap(), 0, x_len );
pf_rebuild_format_string( fmt, &flags ); pf_rebuild_format_string( fmt, &flags );