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: [RFA] strtod: Fix sign bug if exponent is invalid (was Re: [cw@gamma-rs.ch:error in scanf reading %le format and 00 exponent])


Corinna Vinschen wrote:
On Mar 7 11:14, Christopher Faylor wrote:

----- Forwarded message from "Charles L. Werner" -----
#include <stdio.h>
main()
{
 double a;
 while(1){
   printf("input: ");
   scanf("%le",&a);
   printf("a: %le\n",a);
 }
}

input: -.11e+00
a: 1.100000e-01   !akkk

input: -1.1e+00
a: 1.100000e+00   !akkk


Below is a fix for the above problem. The cause is two-fold:

In __svfscanf_r, the expression "-1.1e+00" is copied over to buf, the buffer
used in a later call to strtod.  The problem here is that all leading zeros
in the exponent are skipped, not copied.  The result here is that the
expression given to _strtod_r has an invalid exponent:

"-1.1e+"

this would usually still give the correct result, but now the second bug
hits the ground. As soon as _strtod_r findes the exponent marker 'e' or
'E', the s00 variable which so far pointed to the beginning of the incoming
string, is changed and set to the address of the 'e' or 'E' character.


Unfortunately, there's no valid exponent, so the 'e' or 'E' character is
the first character which doesn't belong to the number and has to be
returned in *se. That's done by setting s to s00. Given that s00 has
been changed accordingly, that's correct.


But now take a look into the return statement of _strtod_r:

return (sign && (s != s00)) ? -rv.d : rv.d;

Bingo.

The below patch only fixes _strtod_r, since that's sufficient to solve
the problem.

However, a full solution also changes __svfscanf_r so that a 0 exponent
is correctly copied to buf.  Right now, I don't see how to do this
elegantly.  In theory it requires another value in the `flags' variable
AFAICS.


Thanks for catching this Corinna. Please check it in. There is no need to post a fix in vfscanf. The reason is that if the exponent is 0, then strtod or strtold stopping processing at that point is still correct. vscanf has already preparsed and verified the input string; it does use the endptr so it doesn't matter that it gets set to the unprocessed exponent.


-- Jeff J.


Corinna


* libc/stdlib/strtod.c (_strtod_r): Never change s00.

Index: libc/stdlib/strtod.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/strtod.c,v
retrieving revision 1.5
diff -u -p -r1.5 strtod.c
--- libc/stdlib/strtod.c	6 Jan 2005 23:31:56 -0000	1.5
+++ libc/stdlib/strtod.c	31 Mar 2005 17:56:33 -0000
@@ -111,7 +111,7 @@ _DEFUN (_strtod_r, (ptr, s00, se),
   int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e1, esign, i, j,
     k, nd, nd0, nf, nz, nz0, sign;
   long e;
-  _CONST char *s, *s0, *s1;
+  _CONST char *s, *s0, *s1, *s2;
   double aadj, aadj1, adj;
   long L;
   unsigned long z;
@@ -222,7 +222,7 @@ dig_done:
 	  s = s00;
 	  goto ret;
 	}
-      s00 = s;
+      s2 = s;
       esign = 0;
       switch (c = *++s)
 	{
@@ -253,7 +253,7 @@ dig_done:
 	    e = 0;
 	}
       else
-	s = s00;
+	s = s2;
     }
   if (!nd)
     {



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