[gfortran] patch to fix PR 16908, segfault on direct access I/O

Bud Davis bdavis9659@comcast.net
Sat Aug 21 11:20:00 GMT 2004


This patch corrects the problem in the PR as well as NIST F77 tests
FM917.FOR and FM921.FOR. (and it doesn't break any new NIST F77 tests
either:)
 
we were padding the record with blanks, which is not what g77 does. 

after removing the padding, some testsuite failures showed up which were
caused by the calculation for NEXTREC, fixed by accounting for records
that are not a full reclen long.


Here is a test suite file, which is exactly as submitted with the PR.
This test aborts before and passes after the patch is applied.

! pr 16908
! segfaults on second set of writes
   program synsig
 
   implicit none
 
   integer n, nt, mt, m
   real dt, tm, w
   real, allocatable :: p(:)
 
   nt =  2049 ! if nt < 2049, then everything works.
  
   allocate(p(nt))
   p  = 0.e0
 
   inquire(iolength=mt) (p(m), m=1, nt)
 
   open(unit=12, file='syn.sax', access='direct', recl=mt)
   n = 1
   write(12, rec=n) mt, nt
   write(12, rec=n+1) (p(m), m=1, nt)
   close(12)
 
   inquire(iolength=mt) (p(m), m=1, nt)
 
   open(unit=12, file='syn.sax', access='direct', recl=mt)
   n = 1
   write(12, rec=n) mt, nt
   write(12, rec=n+1) (p(m), m=1, nt)
   close(12)
 
   end program synsig

and a changelog


2004-08-20  Bud Davis  <bdavis9659@comcast.net>

	PR 16908
	* io/transfer.c (next_record_w): Do not blank pad.
	* io/transfer.c (next_record): Take into account partial 	records.
	

tested with no additional test suite failures on gnu/linux/i686 FC1.


--bud





Index: gcc/libgfortran/io/transfer.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/transfer.c,v
retrieving revision 1.9
diff -c -3 -p -r1.9 transfer.c
*** gcc/libgfortran/io/transfer.c	18 Aug 2004 01:20:06 -0000	1.9
--- gcc/libgfortran/io/transfer.c	21 Aug 2004 04:37:57 -0000
*************** next_record_w (int done)
*** 1223,1242 ****
    switch (current_mode ())
      {
      case FORMATTED_DIRECT:
-     case UNFORMATTED_DIRECT:
        if (current_unit->bytes_left == 0)
  	break;
  
        length = current_unit->bytes_left;
- 
        p = salloc_w (current_unit->s, &length);
        if (p == NULL)
  	goto io_error;
  
        memset (p, ' ', current_unit->bytes_left);
        if (sfree (current_unit->s) == FAILURE)
  	goto io_error;
  
        break;
  
      case UNFORMATTED_SEQUENTIAL:
--- 1223,1245 ----
    switch (current_mode ())
      {
      case FORMATTED_DIRECT:
        if (current_unit->bytes_left == 0)
  	break;
  
        length = current_unit->bytes_left;
        p = salloc_w (current_unit->s, &length);
+ 
        if (p == NULL)
  	goto io_error;
  
        memset (p, ' ', current_unit->bytes_left);
        if (sfree (current_unit->s) == FAILURE)
  	goto io_error;
+       break;
  
+     case UNFORMATTED_DIRECT:
+       if (sfree (current_unit->s) == FAILURE)
+         goto io_error;
        break;
  
      case UNFORMATTED_SEQUENTIAL:
*************** next_record_w (int done)
*** 1304,1309 ****
--- 1307,1313 ----
  void
  next_record (int done)
  {
+   gfc_offset fp; /* file position */
  
    current_unit->read_bad = 0;
  
*************** next_record (int done)
*** 1314,1321 ****
  
    current_unit->current_record = 0;
    if (current_unit->flags.access == ACCESS_DIRECT)
!     current_unit->last_record = file_position (current_unit->s) 
!                                / current_unit->recl;
    else
      current_unit->last_record++;
  
--- 1318,1330 ----
  
    current_unit->current_record = 0;
    if (current_unit->flags.access == ACCESS_DIRECT)
!    {
!     fp = file_position (current_unit->s);
!     current_unit->last_record = fp / current_unit->recl;
!     /* round up if partial */
!     if (fp % current_unit->recl)
!       current_unit->last_record++;
!    }
    else
      current_unit->last_record++;
  






More information about the Gcc-patches mailing list