diff mbox

[libgfortran,4.9/4.10,Regression] Internal read of negative integer broken

Message ID 53AB7E5F.7010205@charter.net
State New
Headers show

Commit Message

Jerry DeLisle June 26, 2014, 1:58 a.m. UTC
Hi,

This bug has nothing to do with negative numbers as in the description.
However, the problem is due to seeking when there are no spaces to skip.  I
restructured the loop so that the skipping is not done if there are no spaces.

Regression tested on x86-64.  New test case from the PR.

OK for trunk and 4.9?

Regards,

Jerry

2014-06-25  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/61499
	* io/list_read.c (eat_spaces): Use a 'for' loop instead of
	'while' loop to skip the loop if there are no bytes left in the
	string. Only seek if actual spaces can be skipped.

Comments

Paul Richard Thomas June 26, 2014, 11:29 a.m. UTC | #1
Hi Jerry,

The patch looks to be OK for trunk.

Did you check it with the NIST by any chance?

Thanks a lot

Paul


On 26 June 2014 03:58, Jerry DeLisle <jvdelisle@charter.net> wrote:
> Hi,
>
> This bug has nothing to do with negative numbers as in the description.
> However, the problem is due to seeking when there are no spaces to skip.  I
> restructured the loop so that the skipping is not done if there are no spaces.
>
> Regression tested on x86-64.  New test case from the PR.
>
> OK for trunk and 4.9?
>
> Regards,
>
> Jerry
>
> 2014-06-25  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
>
>         PR libgfortran/61499
>         * io/list_read.c (eat_spaces): Use a 'for' loop instead of
>         'while' loop to skip the loop if there are no bytes left in the
>         string. Only seek if actual spaces can be skipped.
Jerry DeLisle June 27, 2014, 1:54 a.m. UTC | #2
On 26/06/14 04:29, Paul Richard Thomas wrote:
> Hi Jerry,
> 
> The patch looks to be OK for trunk.
> 
> Did you check it with the NIST by any chance?
> 

Yes, tested fine.

Jerry
diff mbox

Patch

Index: io/list_read.c
===================================================================
--- io/list_read.c	(revision 211765)
+++ io/list_read.c	(working copy)
@@ -387,50 +387,39 @@  eat_spaces (st_parameter_dt *dtp)
   int c;
 
   /* If internal character array IO, peak ahead and seek past spaces.
-     This is an optimazation to eliminate numerous calls to
-     next character unique to character arrays with large character
-     lengths (PR38199). */
-  if (is_array_io (dtp))
+     This is an optimization unique to character arrays with large
+     character lengths (PR38199).  This code eliminates numerous calls
+     to next_character.  */
+  if (is_array_io (dtp) && (dtp->u.p.last_char == EOF - 1))
     {
       gfc_offset offset = stell (dtp->u.p.current_unit->s);
-      gfc_offset limit = offset + dtp->u.p.current_unit->bytes_left;
+      gfc_offset i;
 
       if (dtp->common.unit) /* kind=4 */
 	{
-	  gfc_char4_t cc;
-	  limit *= (sizeof (gfc_char4_t));
-	  do
+	  for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
 	    {
-	      cc = dtp->internal_unit[offset];
-	      offset += (sizeof (gfc_char4_t));
-	      dtp->u.p.current_unit->bytes_left--;
+	      if (dtp->internal_unit[offset + i * sizeof (gfc_char4_t)]
+		  != (gfc_char4_t)' ')
+	        break;
 	    }
-	  while (offset < limit && cc == (gfc_char4_t)' ');
-	  /* Back up, seek ahead, and fall through to complete the
-	     process so that END conditions are handled correctly.  */
-	  dtp->u.p.current_unit->bytes_left++;
-
-	  cc = dtp->internal_unit[offset];
-	  if (cc != (gfc_char4_t)' ')
-	    sseek (dtp->u.p.current_unit->s,
-		   offset-(sizeof (gfc_char4_t)), SEEK_SET);
 	}
       else
 	{
-	  do
+	  for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
 	    {
-	      c = dtp->internal_unit[offset++];
-	      dtp->u.p.current_unit->bytes_left--;
+	      if (dtp->internal_unit[offset + i] != ' ')
+	        break;
 	    }
-	  while (offset < limit && c == ' ');
-	  /* Back up, seek ahead, and fall through to complete the
-	     process so that END conditions are handled correctly.  */
-	  dtp->u.p.current_unit->bytes_left++;
+	}
 
-	  if (dtp->internal_unit[offset] != ' ')
-	    sseek (dtp->u.p.current_unit->s, offset - 1, SEEK_SET);
+      if (i != 0)
+	{
+	  sseek (dtp->u.p.current_unit->s, offset + i, SEEK_SET);
+	  dtp->u.p.current_unit->bytes_left -= i;
 	}
     }
+
   /* Now skip spaces, EOF and EOL are handled in next_char.  */
   do
     c = next_char (dtp);