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]

[RFA] __svfscanf_r: Fix zero exponent handling (was 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]))


On Mar 31 20:12, 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
> [...]
> 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+"
> [...]

Attached is a patch to __svfscanf_r which solves the above part of the
problem.  It copies the first zero in the exponent and notes this fact.
Then, if a non-zero digit follows, it sets p back to overwrite the leading
zero again.  The latter overwriting could be savely dropped, since the
leading zero wouldn't hurt strtod.  I added it to this patch anyway for
cleanness.


Corinna

	* libc/stdio/vfscanf.c (FZINEXP): New flag value.
	(__SVFSCANF_R): Copy over first zero in exponent to buf.  Overwrite
	if non-zero digit follows.

Index: libc/stdio/vfscanf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfscanf.c,v
retrieving revision 1.28
diff -u -p -r1.28 vfscanf.c
--- libc/stdio/vfscanf.c	8 Feb 2005 01:33:17 -0000	1.28
+++ libc/stdio/vfscanf.c	31 Mar 2005 19:25:36 -0000
@@ -194,6 +194,7 @@ extern _LONG_DOUBLE _strtold _PARAMS((ch
 #define	PFXOK		0x200	/* 0x prefix is (still) legal */
 #define	NZDIGITS	0x400	/* no zero digits detected */
 #define	NNZDIGITS	0x800	/* no non-zero digits detected */
+#define	FZINEXP		0x1000	/* first leading zero in exponent detected */
 
 /*
  * Conversion types.
@@ -1020,6 +1021,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
 			  width_left--;
 			  width++;
 			}
+		      if (!(flags & (EXPOK | FZINEXP)))
+		        {
+			  /* Found first leading zero in exponent. 
+			     Don't skip it in output. */
+			  flags |= FZINEXP;
+			  goto fok;
+			}
 		      goto fskip;
 		    }
 		  /* Fall through.  */
@@ -1035,6 +1043,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
 		  if (nancount == 0)
 		    {
 		      flags &= ~(SIGNOK | NDIGITS);
+		      /* Drop leading zero in exponent if a non-zero
+		         digit follows. */
+		      if (flags & FZINEXP)
+		        {
+			  --p;
+			  flags &= ~FZINEXP;
+			}
 		      goto fok;
 		    }
 		  break;

-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat, Inc.


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