public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, libfortran] PR 19155 Parsing invalid floating point input and EINVAL
@ 2011-05-28 15:44 Janne Blomqvist
  2011-05-28 19:16 ` Steve Kargl
  0 siblings, 1 reply; 2+ messages in thread
From: Janne Blomqvist @ 2011-05-28 15:44 UTC (permalink / raw)
  To: GCC Patches, Fortran List

[-- Attachment #1: Type: text/plain, Size: 1188 bytes --]

Hi,

Steve Ellcey reported that gfortran.dg/pr19155.f fails on HP-UX 11.31
because on that target strtod sets errno to EINVAL for invalid input,
whereas many other implementations such as glibc does not.

The problem is that C99 says nothing about setting errno to EINVAL for
invalid input, and POSIX merely says that "errno may be set to
[EINVAL]."

http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtod.html

Therefore the portable way of checking for bad input is to check
whether endptr == nptr instead of checking whether errno == EINVAL.
The attached patch does this. In order to support the extension of
parsing an input of style "E+NN" as 0, the patch fixes the string
passed to strtod. This is done only when using an edit descriptor, not
for list input, as with list input there's IMHO a bigger chance we
accidentally parse the wrong thing if we accept stuff like this.

Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

2011-05-28  Janne Blomqvist  <jb@gcc.gnu.org>

	PR libfortran/19155
	* io/read.c (convert_real): Check for invalid input by comparing
	endptr instead of EINVAL.
	(read_f): Fixup floating point input without significand.


-- 
Janne Blomqvist

[-- Attachment #2: fread.f --]
[-- Type: text/x-fortran, Size: 3059 bytes --]

diff --git a/libgcc/configure b/libgcc/configure
old mode 100644
new mode 100755
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 3ee5717..d07d09d 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -131,45 +131,45 @@ max_value (int length, int signed_flag)
 
 
 /* convert_real()-- Convert a character representation of a floating
-   point number to the machine number.  Returns nonzero if there is a
-   range problem during conversion.  Note: many architectures
-   (e.g. IA-64, HP-PA) require that the storage pointed to by the dest
-   argument is properly aligned for the type in question.  */
+   point number to the machine number.  Returns nonzero if there is an
+   invalid input.  Note: many architectures (e.g. IA-64, HP-PA)
+   require that the storage pointed to by the dest argument is
+   properly aligned for the type in question.  */
 
 int
 convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
 {
-  errno = 0;
+  char *endptr = NULL;
 
   switch (length)
     {
     case 4:
       *((GFC_REAL_4*) dest) =
 #if defined(HAVE_STRTOF)
-	gfc_strtof (buffer, NULL);
+	gfc_strtof (buffer, &endptr);
 #else
-	(GFC_REAL_4) gfc_strtod (buffer, NULL);
+	(GFC_REAL_4) gfc_strtod (buffer, &endptr);
 #endif
       break;
 
     case 8:
-      *((GFC_REAL_8*) dest) = gfc_strtod (buffer, NULL);
+      *((GFC_REAL_8*) dest) = gfc_strtod (buffer, &endptr);
       break;
 
 #if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
     case 10:
-      *((GFC_REAL_10*) dest) = gfc_strtold (buffer, NULL);
+      *((GFC_REAL_10*) dest) = gfc_strtold (buffer, &endptr);
       break;
 #endif
 
 #if defined(HAVE_GFC_REAL_16)
 # if defined(GFC_REAL_16_IS_FLOAT128)
     case 16:
-      *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
+      *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
       break;
 # elif defined(HAVE_STRTOLD)
     case 16:
-      *((GFC_REAL_16*) dest) = gfc_strtold (buffer, NULL);
+      *((GFC_REAL_16*) dest) = gfc_strtold (buffer, &endptr);
       break;
 # endif
 #endif
@@ -178,10 +178,10 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
       internal_error (&dtp->common, "Unsupported real kind during IO");
     }
 
-  if (errno == EINVAL)
+  if (buffer == endptr)
     {
       generate_error (&dtp->common, LIBERROR_READ_VALUE,
-		      "Error during floating point read");
+  		      "Error during floating point read");
       next_record (dtp, 1);
       return 1;
     }
@@ -1114,6 +1114,14 @@ done:
   /* Output a trailing '0' after decimal point if not yet found.  */
   if (seen_dp && !seen_dec_digit)
     *(out++) = '0';
+  /* Handle input of style "E+NN" by inserting a 0 for the
+     significand.  */
+  else if (!seen_int_digit && !seen_dec_digit)
+    {
+      notify_std (&dtp->common, GFC_STD_LEGACY, 
+		  "REAL input of style 'E+NN'");
+      *(out++) = '0';
+    }
 
   /* Print out the exponent to finish the reformatted number.  Maximum 4
      digits for the exponent.  */

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Patch, libfortran] PR 19155 Parsing invalid floating point input and EINVAL
  2011-05-28 15:44 [Patch, libfortran] PR 19155 Parsing invalid floating point input and EINVAL Janne Blomqvist
@ 2011-05-28 19:16 ` Steve Kargl
  0 siblings, 0 replies; 2+ messages in thread
From: Steve Kargl @ 2011-05-28 19:16 UTC (permalink / raw)
  To: Janne Blomqvist; +Cc: GCC Patches, Fortran List

On Sat, May 28, 2011 at 11:18:13AM +0300, Janne Blomqvist wrote:
> 
> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
> 
> 2011-05-28  Janne Blomqvist  <jb@gcc.gnu.org>
> 
> 	PR libfortran/19155
> 	* io/read.c (convert_real): Check for invalid input by comparing
> 	endptr instead of EINVAL.
> 	(read_f): Fixup floating point input without significand.

Yes.  Thanks for the patch.

-- 
Steve

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-05-28 15:44 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-28 15:44 [Patch, libfortran] PR 19155 Parsing invalid floating point input and EINVAL Janne Blomqvist
2011-05-28 19:16 ` Steve Kargl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).