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