Jesse Allen : msvcrt: Estimate required buffer size better in
pf_vsnprintf.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Nov 14 05:14:20 CST 2006
Module: wine
Branch: master
Commit: 5b75c86921e41f794bd8d126bb37f08f8c63b36d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5b75c86921e41f794bd8d126bb37f08f8c63b36d
Author: Jesse Allen <the3dfxdude at gmail.com>
Date: Mon Nov 13 20:55:02 2006 -0700
msvcrt: Estimate required buffer size better in pf_vsnprintf.
---
dlls/msvcrt/wcs.c | 42 +++++++++++++++++++++++++++++++++---------
1 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 591f28f..800d3b5 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -281,6 +281,7 @@ static inline int pf_output_stringA( pf_
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 )
{
int i, r = 0;
@@ -426,15 +427,19 @@ static void pf_rebuild_format_string( ch
*p++ = 0;
}
-/* pf_integer_conv: prints x to buf, including alternate formats,
- but not the sign */
-static void pf_integer_conv( char *buf, pf_flags *flags, LONGLONG x )
+/* pf_integer_conv: prints x to buf, including alternate formats and
+ additional precision digits, but not field characters or the sign */
+static void pf_integer_conv( char *buf, int buf_len, pf_flags *flags,
+ LONGLONG x )
{
unsigned int base;
const char *digits;
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;
if( flags->Format == 'o' )
@@ -487,6 +492,9 @@ static void pf_integer_conv( char *buf,
/* Adjust precision so pf_fill won't truncate the number later */
flags->Precision = strlen( buf );
+ if( tmp != number )
+ HeapFree( GetProcessHeap(), 0, tmp );
+
return;
}
@@ -660,10 +668,18 @@ static int pf_vsnprintf( pf_output *out,
{
char number[40], *x = number;
- if( flags.FieldLength >= sizeof number )
- x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 );
+ /* Estimate largest possible required buffer size:
+ * 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 );
if( x != number )
@@ -675,8 +691,16 @@ static int pf_vsnprintf( pf_output *out,
{
char fmt[20], number[40], *x = number;
- if( flags.FieldLength >= sizeof number )
- x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 );
+ /* Estimate largest possible required buffer size:
+ * 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 );
More information about the wine-cvs
mailing list