bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] strtod: work around IRIX 6.5 bug


From: Eric Blake
Subject: [PATCH] strtod: work around IRIX 6.5 bug
Date: Wed, 1 Sep 2010 21:49:58 -0600

IRIX mis-parses "1e 1" as 10.0 and "" instead of 1.0 and "e 1".
Because the original parse may differ from the reparse in terms
of whether the value overflows, we have to do an errno dance.

* lib/strtod.c (strtod): Reparse number on shorter string if
exponent parse was invalid.
Reported by Tom G. Christensen.

Signed-off-by: Eric Blake <address@hidden>
---

>> Building with MIPSpro works but there are testsuite failures:
>> $ ./test-strtod
>> test-strtod.c:377: assertion failed
>> Abort (core dumped)
>
>Phooey - a regression.  This is already a known bug ("1E 2" is
>mistakenly treated as 100.0 instead of 1.0 on HP-UX 11.11, IRIX 6.5,
>and OSF/1 4.0, per the comments on that line); so our rewrite to call
>the native strtod under the hood of rpl_strtod is not working around
>this particular bug.

This should do it.  I've compile-tested it, but without an actual
platform exhibiting the failure, there may still be a tweak or
two needed.

Hmm - the testsuite lacks any tests for "0x1p 1" not consuming the
"p 1".  I wonder if AIX is buggy in that regards; and if so, the
errno dance needs to be extended to 0x handling.  I guess I'd better
do a followup that enhances the testsuite, yet again.

 ChangeLog    |    7 +++++++
 lib/strtod.c |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2955f2f..395191a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-09-01  Eric Blake  <address@hidden>
+
+       strtod: work around IRIX 6.5 bug
+       * lib/strtod.c (strtod): Reparse number on shorter string if
+       exponent parse was invalid.
+       Reported by Tom G. Christensen.
+
 2010-08-31  Eric Blake  <address@hidden>
        and Jim Meyering  <address@hidden>

diff --git a/lib/strtod.c b/lib/strtod.c
index 64b62ff..944f6cd 100644
--- a/lib/strtod.c
+++ b/lib/strtod.c
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include <math.h>
 #include <stdbool.h>
+#include <string.h>

 #include "c-ctype.h"

@@ -202,6 +203,7 @@ strtod (const char *nptr, char **endptr)
   const char *s = nptr;
   const char *end;
   char *endbuf;
+  int saved_errno;

   /* Eat whitespace.  */
   while (locale_isspace (*s))
@@ -212,6 +214,7 @@ strtod (const char *nptr, char **endptr)
   if (*s == '-' || *s == '+')
     ++s;

+  saved_errno = errno;
   num = underlying_strtod (s, &endbuf);
   end = endbuf;

@@ -239,6 +242,35 @@ strtod (const char *nptr, char **endptr)
                 end = p;
             }
         }
+      else
+        {
+          /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
+             underlying strtod on a copy of the original string
+             truncated to avoid the bug.  */
+          const char *e = s + 1;
+          while (e < end && c_tolower (*e) != 'e')
+            e++;
+          if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
+            {
+              char *dup = strdup (s);
+              errno = saved_errno;
+              if (!dup)
+                {
+                  /* Not really our day, is it.  Rounding errors are
+                     better than outright failure.  */
+                  num = parse_number (s, 10, 10, 1, 'e', &endbuf);
+                }
+              else
+                {
+                  dup[e - s] = '\0';
+                  num = underlying_strtod (s, &endbuf);
+                  saved_errno = errno;
+                  free (dup);
+                  errno = saved_errno;
+                }
+              end = e;
+            }
+        }

       s = end;
     }
-- 
1.7.2.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]