This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gfortran-4.1.2 file io bug fix


Dear Jerry, dear Steve,

It's me again, this time about a patch against another Fortran file IO bug
found in the newest release gcc-4.1.2.

The program I am working on reads a previously created sequential
unformatted file. It reads the file record by record searching for a
specific contents. The records have different lengths and they are sometimes
shorter than the array they are read to. The algorithm worked fine under
gfortran-4.1.1. But gfortran-4.1.2 introduced a new kind of error:
ERROR_SHORT_RECORD whose condition was simply ignored by gfortran-4.1.1. The
existence of this new feature itself is not a problem at all. But just after
ERROR_SHORT_RECORD libgfortran gets out of sync, looses the record markers
and gives an end-of-file condition on all subsequent reads although there
should be a lot of further records present.

I have reduced the test to a small demo program. This program writes
sequentially five records: 32, 16, 32, 16, 32 bytes long. Then it rewinds
the file and reads all them again, this procedure goes fine under both
gfortran-4.1.1 and 4.1.2. Then it rewinds again and tries to read 32 bytes
five times. It goes fine under gfortran-4.1.1 as it ignores short records.
Gfortran-4.1.2 gives a proper error condition at the second read. I dont
know the Fortran 95 standard so good, I rely on the supposition that there
must be really an error condition in this case. But I'd expect the following
record (32 bytes long) should be read correctly. But it isn't. The program
gets two times end-of-file, and again an error for the very last read.

After some debugging I created a patch against gcc-4.1.2 which corrects my
problem. Now libgfortran gives ERROR_SHORT_RECORD for the records number 2
and 4 (16 bytes) and continues to read correctly all the other records. And
the real program where I have seen the problem for the first time works now
also.

But I am not so experienced gfortran hacker, and the place I tried to
correct looks rather complex. I am not sure if my patch corrects all the
possible cases. Could you please review this peace of code?

The proposed patch against gcc-4.1.2 is here:

diff -Naur gcc-4.1.2.orig/libgfortran/io/transfer.c gcc-4.1.2/libgfortran/io/transfer.c
--- gcc-4.1.2.orig/libgfortran/io/transfer.c	2006-12-26 04:56:54.000000000 +0600
+++ gcc-4.1.2/libgfortran/io/transfer.c	2007-03-29 18:54:02.000000000 +0700
@@ -348,6 +348,8 @@
   if (short_record)
     {
       generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL);
+      dtp->u.p.current_unit->current_record = 0;
+      next_record (dtp, 1);
       return;
     }

The test program which demonstrates the bug is here (compile with
--std=legacy).

      PROGRAM TEST
      CHARACTER*8 A(2), B(4), C
      A(1) = '***A1***'
      A(2) = '***A2***'
      B(1) = '***B1***'
      B(2) = '***B2***'
      B(3) = '***B3***'
      B(4) = '***B4***'
      OPEN (1, FILE='TEST', STATUS='UNKNOWN', FORM='UNFORMATTED')
      PRINT *, 'WRITING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)'
      WRITE (1) B
      WRITE (1) A
      WRITE (1) B
      WRITE (1) A
      WRITE (1) B
      PRINT *, 'REWINDING FILE'
      REWIND 1
      PRINT *, 'READING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)'
      ASSIGN 1 TO M
      C = 'B(4)'
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 4    FORMAT (A/4(A8/))
 1    ASSIGN 5 TO M
      C = 'A(2)'
      READ (1, ERR=2, END=3) A
      PRINT 4, C, A
 5    ASSIGN 6 TO M
      C = 'B(4)'
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 6    ASSIGN 7 TO M
      C = 'A(2)'
      READ (1, ERR=2, END=3) A
      PRINT 4, C, A
 7    ASSIGN 8 TO M
      C = 'B(4)'
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 8    PRINT *, 'REWINDING FILE'
      REWIND 1
      PRINT *, 'READING FIVE ARRAYS: B(4), B(4), B(4), B(4), B(4)'
      ASSIGN 9 TO M
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 9    ASSIGN 10 TO M
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 10   ASSIGN 11 TO M
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 11   ASSIGN 12 TO M
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 12   ASSIGN 13 TO M
      READ (1, ERR=2, END=3) B
      PRINT 4, C, B
 13   STOP
 2    PRINT 14, C, A, B
 14   FORMAT ('ERROR READING ',A/'A(2)'/2(A8/)'B(4)'/4(A8/))
      GOTO M
 3    PRINT 15, C, A, B
 15   FORMAT ('ENDFILE READING ',A/'A(2)'/2(A8/)'B(4)'/4(A8/))
      GOTO M
      END

The output of this program under gcc-4.1.1 (no errors at all) is:

 WRITING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
 REWINDING FILE
 READING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

 REWINDING FILE
 READING FIVE ARRAYS: B(4), B(4), B(4), B(4), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

B(4)
***A1***
***A2***
***B3***
***B4***

B(4)
***B1***
***B2***
***B3***
***B4***

B(4)
***A1***
***A2***
***B3***
***B4***

B(4)
***B1***
***B2***
***B3***
***B4***

Under unpatched gcc-4.1.2 (a complete mess after the first short record) is:

 WRITING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
 REWINDING FILE
 READING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

 REWINDING FILE
 READING FIVE ARRAYS: B(4), B(4), B(4), B(4), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

ERROR READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

ENDFILE READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

ENDFILE READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

ERROR READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

And under patched gcc-4.1.2 (errors on short records, otherwise fine) is:

 WRITING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
 REWINDING FILE
 READING FIVE ARRAYS: B(4), A(2), B(4), A(2), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

A(2)
***A1***
***A2***

B(4)
***B1***
***B2***
***B3***
***B4***

 REWINDING FILE
 READING FIVE ARRAYS: B(4), B(4), B(4), B(4), B(4)
B(4)
***B1***
***B2***
***B3***
***B4***

ERROR READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

B(4)
***B1***
***B2***
***B3***
***B4***

ERROR READING B(4)
A(2)
***A1***
***A2***
B(4)
***A1***
***A2***
***B3***
***B4***

B(4)
***B1***
***B2***
***B3***
***B4***

Kind regards,
Georgy.
_______________________________________________________________________________

Georgy Salnikov
NMR Group
Novosibirsk Institute of Organic Chemistry
Lavrentjeva, 9, 630090 Novosibirsk, Russia
Tel.   +7-383-3307864   +7-383-3331456
Fax                     +7-383-3331456
Email   sge@nmr.nioch.nsc.ru
_______________________________________________________________________________


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]