This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug in vfprintf?


I found a problem.  My fix was using ndigits instead of
orig_ndigits for the "%g" format.  A revised patch is attached.

-- Jeff J.

Jason Tishler wrote:
Jeff,

On Fri, Jan 31, 2003 at 07:56:05PM -0500, J. Johnston wrote:

Ok, another patch for you.

The attached patch fixes my most recently reported problems with "%f"
formatting.  However, my previously reported problem with:

    "%#.109g", -3333333333333333371313292264111748921061485000000.0

is back.

Unfortunately, I'm having difficulties isolating the problem in C, but
the following simple Python script SEGVs during exit (i.e., during
garbage collection):

    s = "%#.109g" % (-1.e+49/3.)
    print s

Attached is my C translation of the above.  Single stepping in gdb, I
haven't found the overwrite yet.  I will try to dig deeper, but I hope
that reporting what I have found will help you see what I'm missing.

Thanks,
Jason



------------------------------------------------------------------------

#include <stdio.h>

int
main(int argc, char* argv[])
{
	const char* format = "%#.109g";
	double value = -1.e+49/3.;
	printf(format, value);
	printf("\n");
	return 0;
}

Index: ldtoa.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/ldtoa.c,v
retrieving revision 1.7
diff -u -r1.7 ldtoa.c
--- ldtoa.c	7 Jan 2003 19:52:27 -0000	1.7
+++ ldtoa.c	3 Feb 2003 17:12:33 -0000
@@ -2707,10 +2707,13 @@
 unsigned short e[NI];
 char *s, *p;
 int i, j, k;
+int orig_ndigits;
 LDPARMS rnd;
 LDPARMS *ldp = &rnd;
 char *outstr;
+char outbuf[NDEC + MAX_EXP_DIGITS + 10];
 
+orig_ndigits = ndigits;
 rnd.rlast = -1;
 rnd.rndprc = NBITS;
 
@@ -2748,22 +2751,13 @@
 if( mode == 0 )
         ndigits = 20;
 
-/* reentrancy addition to use mprec storage pool */
-/* we want to have enough space to hold the formatted result */
-i = ndigits + (mode == 3 ? (MAX_EXP_DIGITS + 1) : 1);
-j = sizeof (__ULong);
-for (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1)
-  _REENT_MP_RESULT_K(ptr)++;
-_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));
-outstr = (char *)_REENT_MP_RESULT(ptr);
-
 /* This sanity limit must agree with the corresponding one in etoasc, to
    keep straight the returned value of outexpon.  */
 if( ndigits > NDEC )
         ndigits = NDEC;
 
-etoasc( e, outstr, ndigits, mode, ldp );
-s =  outstr;
+etoasc( e, outbuf, ndigits, mode, ldp );
+s =  outbuf;
 if( eisinf(e) || eisnan(e) )
         {
         *decpt = 9999;
@@ -2774,7 +2768,7 @@
 /* Transform the string returned by etoasc into what the caller wants.  */
 
 /* Look for decimal point and delete it from the string. */
-s = outstr;
+s = outbuf;
 while( *s != '\0' )
         {
         if( *s == '.' )
@@ -2795,19 +2789,19 @@
 nodecpt:
 
 /* Back up over the exponent field. */
-while( *s != 'E' && s > outstr)
+while( *s != 'E' && s > outbuf)
         --s;
 *s = '\0';
 
 stripspaces:
 
 /* Strip leading spaces and sign. */
-p = outstr;
+p = outbuf;
 while( *p == ' ' || *p == '-')
         ++p;
 
 /* Find new end of string.  */
-s = outstr;
+s = outbuf;
 while( (*s++ = *p++) != '\0' )
         ;
 --s;
@@ -2820,20 +2814,38 @@
 else
         k = ldp->outexpon;
 
-while( *(s-1) == '0' && ((s - outstr) > k))
+while( *(s-1) == '0' && ((s - outbuf) > k))
         *(--s) = '\0';
 
 /* In f format, flush small off-scale values to zero.
    Rounding has been taken care of by etoasc. */
 if( mode == 3 && ((ndigits + ldp->outexpon) < 0))
         {
-        s = outstr;
+        s = outbuf;
         *s = '\0';
         *decpt = 0;
         }
 
+/* reentrancy addition to use mprec storage pool */
+/* we want to have enough space to hold the formatted result */
+
+if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */
+  i = *decpt + orig_ndigits + 3;
+else /* account for sign + max precision digs + E + exp sign + exponent */
+  i = orig_ndigits + MAX_EXP_DIGITS + 4;
+
+j = sizeof (__ULong);
+for (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1)
+  _REENT_MP_RESULT_K(ptr)++;
+_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));
+
+/* Copy from internal temporary buffer to permanent buffer.  */
+outstr = (char *)_REENT_MP_RESULT(ptr);
+strcpy (outstr, outbuf);
+
 if( rve )
-        *rve = s;
+        *rve = outstr + (s - outbuf);
+
 return outstr;
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]