From: tkoenig Date: Wed, 6 Dec 2006 19:25:44 +0000 (+0000) Subject: 2006-12-06 Thomas Koenig X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=71b434375ccd926bd610e095901a31ff01696b7c 2006-12-06 Thomas Koenig 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 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 --- 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 + + 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 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 . +! Submitted by Jerry DeLisle , modified by +! Thomas Koenig + 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 + + 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 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;