summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-06 19:25:44 +0000
committertkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-06 19:25:44 +0000
commit71b434375ccd926bd610e095901a31ff01696b7c (patch)
treeca8a396e07dee2ad42be8eab7d5520d8281b63b1
parent9430e4a9f2fce8b320791543db932fbdb69ea6ca (diff)
downloadgcc-71b434375ccd926bd610e095901a31ff01696b7c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119592 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gfortran.dg/read_eof_4.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f9027
-rw-r--r--libgfortran/ChangeLog18
-rw-r--r--libgfortran/io/transfer.c58
-rw-r--r--libgfortran/libgfortran.h1
-rw-r--r--libgfortran/runtime/error.c4
8 files changed, 118 insertions, 39 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 089232fa404..58837bc40ac 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gfortran.dg/read_eof_4.f90 b/gcc/testsuite/gfortran.dg/read_eof_4.f90
index b8ca5a78e57..ee95268d50d 100644
--- a/gcc/testsuite/gfortran.dg/read_eof_4.f90
+++ b/gcc/testsuite/gfortran.dg/read_eof_4.f90
@@ -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
index 00000000000..2c19eba3927
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90
@@ -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
index 00000000000..166d5291530
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90
@@ -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
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 8844e9ad336..eca621b172e 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -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
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 4270d61e693..163557d49b3 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -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;
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 644a0adc784..c6b31ed908a 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -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;
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index 122f6d14bab..35955644ba5 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -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;