]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libfortran/30009 ([4.1 only] Unformatted reads exceeding storage units gives...
authorThomas Koenig <Thomas.Koenig@online.de>
Wed, 6 Dec 2006 19:25:44 +0000 (19:25 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 6 Dec 2006 19:25:44 +0000 (19:25 +0000)
2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>

PR libfortran/30009
PR libfortran/30056
* gfortran.dg/read_eof_4.f90:  Add tests.
* gfortran.dg/readwrite_unf_direct_eor_1.f90:  New test.
* gfortran.dg/unf_read_corrupted_1.f90: New test.

2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>

PR libfortran/30009
PR libfortran/30056
* libgfortran.h:  Add ERROR_CORRUPT_FILE to error_codes.
* runtime/error.c (translate_error):  Add handling for
ERROR_CORRUPT_FILE.
* io/transfer.c (read_block_direct):  Add comment about
EOR for stream files.
Remove test for no bytes left for direct access files.
Generate an ERROR_SHORT_RECORD if the read was short.
For unformatted sequential files:  Check endfile condition.
Remove test for no bytes left.  End of file here means
that the file structure has been corrupted.  Pre-position
the file for the next record in case of error.
(write_buf):  Whitespace fix.  Subtract the number of bytes
written from bytes_left.

From-SVN: r119592

gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/read_eof_4.f90
gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/io/transfer.c
libgfortran/libgfortran.h
libgfortran/runtime/error.c

index 089232fa404a7d28fc4b89311dc5a3568f678da5..58837bc40ac72b2bc526d8666b1d30906a634e4b 100644 (file)
@@ -1,3 +1,11 @@
+2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>
+
+       PR libfortran/30009
+       PR libfortran/30056
+       * gfortran.dg/read_eof_4.f90:  Add tests.
+       * gfortran.dg/readwrite_unf_direct_eor_1.f90:  New test.
+       * gfortran.dg/unf_read_corrupted_1.f90: New test.
+
 2006-12-05  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/29729
index b8ca5a78e57fb08b0d88772b508433b1e4eb2579..ee95268d50dc13a857f44b4bb94ebb99cbcf8a3c 100644 (file)
@@ -1,16 +1,30 @@
 ! { dg-do run }
-! PR 27575 : This test checks the error checking for end of file condition.
+! PR 27575 and PR 30009: This test checks the error checking for end
+! of file condition.
 ! Derived from test case in PR.
-! Submitted by Jerry DeLisle <jvdelisle@verizon.net>.
+! Submitted by Jerry DeLisle <jvdelisle@verizon.net>, modified by
+! Thomas Koenig <Thomas.Koenig@online.de>
+
       program test
       integer i1,i2,i3
       open(unit=11,form='unformatted')
-      write(11)i1, i2     
+      write (11) 1, 2
+      write (11) 3, 4
       close(11,status='keep')
+
       open(unit=11,form='unformatted')
-      read(11, eND=100) i1, i2, i3
+
+      read(11, ERR=100) i1, i2, i3
       call abort()
- 100  read(11, end=110) i3
-      call abort() 
- 110  close(11,status='delete')
+  100 continue
+      if (i1 /= 1 .or. i2 /= 2) call abort
+
+      read(11, ERR=110) i1, i2, i3
+      call abort()
+  110 continue
+      if (i1 /= 3 .or. i2 /= 4) call abort
+
+      read(11, end=120) i3
+      call abort()
+ 120  close(11,status='delete')
       end
diff --git a/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90 b/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90
new file mode 100644 (file)
index 0000000..2c19eba
--- /dev/null
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR 30056 - exceeding the record length was misrepresented as an EOF
+!            on read and ignored on write 
+      program main
+      integer i,j
+      open (10, form="unformatted", access="direct", recl=4)
+      write (10, rec=1, err=10) 1,2
+      call abort()
+ 10   continue
+      read (10,  rec=1, err=20) i, j
+      call abort()
+ 20   continue
+      end
diff --git a/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90 b/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90
new file mode 100644 (file)
index 0000000..166d529
--- /dev/null
@@ -0,0 +1,27 @@
+! { dg-do run }
+! Test the error message when an unformatted file has become
+! corrupted.
+program main
+  implicit none
+  integer :: i1, i2
+  integer :: ios
+  character(len=50) :: msg
+
+  ! Write out a truncated unformatted sequential file by
+  ! using unformatted stream.
+
+  open (10, form="unformatted", access="stream", file="foo.dat", &
+  status="unknown")
+  write (10) 16, 1
+  close (10, status="keep")
+
+  ! Try to read
+  open (10, file="foo.dat", form="unformatted", access="sequential")
+  i1 = 0
+  i2 = 0
+  read (10, iostat=ios, iomsg=msg) i1, i2
+  if (ios == 0) call abort
+  if (i1 /= 1) call abort
+  if (msg /= "Unformatted file structure has been corrupted") call abort
+  close (10, status="delete")
+end program main
index 8844e9ad336d873e5d95320c50915b6588f3b5e3..eca621b172e075a974c96ffd9db7c8a1f236978f 100644 (file)
@@ -1,3 +1,21 @@
+2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>
+
+       PR libfortran/30009
+       PR libfortran/30056
+       * libgfortran.h:  Add ERROR_CORRUPT_FILE to error_codes.
+       * runtime/error.c (translate_error):  Add handling for
+       ERROR_CORRUPT_FILE.
+       * io/transfer.c (read_block_direct):  Add comment about
+       EOR for stream files.
+       Remove test for no bytes left for direct access files.
+       Generate an ERROR_SHORT_RECORD if the read was short.
+       For unformatted sequential files:  Check endfile condition.
+       Remove test for no bytes left.  End of file here means
+       that the file structure has been corrupted.  Pre-position
+       the file for the next record in case of error.
+       (write_buf):  Whitespace fix.  Subtract the number of bytes
+       written from bytes_left.
+
 2006-12-04  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libfortran/30005
index 4270d61e693cb01410bafd6645330317e3a79f45..163557d49b3a5f8fc61a79df7dfa0c1ad8923638 100644 (file)
@@ -374,7 +374,8 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 
       if (to_read_record != have_read_record)
        {
-         /* Short read,  e.g. if we hit EOF.  */
+         /* Short read,  e.g. if we hit EOF.  For stream files,
+          we have to set the end-of-file condition.  */
          generate_error (&dtp->common, ERROR_END, NULL);
          return;
        }
@@ -388,13 +389,6 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
          short_record = 1;
          to_read_record = (size_t) dtp->u.p.current_unit->bytes_left;
          *nbytes = to_read_record;
-
-         if (dtp->u.p.current_unit->bytes_left == 0)
-           {
-             dtp->u.p.current_unit->endfile = AT_ENDFILE;
-             generate_error (&dtp->common, ERROR_END, NULL);
-             return;
-           }
        }
 
       else
@@ -411,10 +405,12 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
          return;
        }
 
-      if (to_read_record != *nbytes)  /* Short read, e.g. if we hit EOF.  */
+      if (to_read_record != *nbytes)  
        {
+         /* Short read, e.g. if we hit EOF.  Apparently, we read
+          more than was written to the last record.  */
          *nbytes = to_read_record;
-         generate_error (&dtp->common, ERROR_END, NULL);
+         generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL);
          return;
        }
 
@@ -430,6 +426,12 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
      until the request has been fulfilled or the record has run out
      of continuation subrecords.  */
 
+  if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
+    {
+      generate_error (&dtp->common, ERROR_END, NULL);
+      return;
+    }
+
   /* Check whether we exceed the total record length.  */
 
   if (dtp->u.p.current_unit->flags.has_recl)
@@ -453,25 +455,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
        {
          to_read_subrecord = (size_t) dtp->u.p.current_unit->bytes_left_subrecord;
          to_read_record -= to_read_subrecord;
-
-         if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
-           {
-             if (dtp->u.p.current_unit->continued)
-               {
-                 /* Skip to the next subrecord */
-                 next_record_r_unf (dtp, 0);
-                 us_read (dtp, 1);
-                 continue;
-               }
-             else
-               {
-                 dtp->u.p.current_unit->endfile = AT_ENDFILE;
-                 generate_error (&dtp->common, ERROR_END, NULL);
-                 return;
-               }
-           }
        }
-
       else
        {
          to_read_subrecord = to_read_record;
@@ -490,11 +474,15 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 
       have_read_record += have_read_subrecord;
 
-      if (to_read_subrecord != have_read_subrecord)  /* Short read,
-                                                       e.g. if we hit EOF.  */
+      if (to_read_subrecord != have_read_subrecord)  
+                       
        {
+         /* Short read, e.g. if we hit EOF.  This means the record
+            structure has been corrupted, or the trailing record
+            marker would still be present.  */
+
          *nbytes = have_read_record;
-         generate_error (&dtp->common, ERROR_END, NULL);
+         generate_error (&dtp->common, ERROR_CORRUPT_FILE, NULL);
          return;
        }
 
@@ -507,6 +495,11 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
            }
          else
            {
+             /* Let's make sure the file position is correctly set for the
+                next read statement.  */
+
+             next_record_r_unf (dtp, 0);
+             us_read (dtp, 0);
              generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL);
              return;
            }
@@ -637,7 +630,8 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
          return FAILURE;
        }
 
-      dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes; 
+      dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes;
+      dtp->u.p.current_unit->bytes_left -= (gfc_offset) nbytes;
 
       return SUCCESS;
 
index 644a0adc7844557bfaaf50d283d58948c9ef38c3..c6b31ed908a8ff0358381a284a7ab84615fea608 100644 (file)
@@ -416,6 +416,7 @@ typedef enum
   ERROR_ALLOCATION,
   ERROR_DIRECT_EOR,
   ERROR_SHORT_RECORD,
+  ERROR_CORRUPT_FILE,
   ERROR_LAST                   /* Not a real error, the last error # + 1.  */
 }
 error_codes;
index 122f6d14bab426f596b4a45b5ae37441fbd52e0d..35955644ba5fab94593bd7edb242a41ccdce885c 100644 (file)
@@ -440,6 +440,10 @@ translate_error (int code)
       p = "I/O past end of record on unformatted file";
       break;
 
+    case ERROR_CORRUPT_FILE:
+      p = "Unformatted file structure has been corrupted";
+      break;
+
     default:
       p = "Unknown error code";
       break;