This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix libgfortran read_sf (PR fortran/47878)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, fortran at gcc dot gnu dot org
- Date: Thu, 24 Feb 2011 21:16:35 +0100
- Subject: [PATCH] Fix libgfortran read_sf (PR fortran/47878)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
read_sf can return pointer to already freed memory (in case fbuf_getc
results in realloc). The following patch fixes it, bootstrapped/regtested
on x86_64-linux and i686-linux, approved by Jerry in the PR, committed to
trunk.
2011-02-24 Jakub Jelinek <jakub@redhat.com>
PR fortran/47878
* io/transfer.c (read_sf): Call fbuf_getptr only at the end,
and subtract n, dtp->u.p.sf_seen_eor and seen_comma from it.
* gfortran.dg/pr47878.f90: New test.
--- libgfortran/io/transfer.c.jj 2011-02-24 17:33:39.000000000 +0100
+++ libgfortran/io/transfer.c 2011-02-24 18:17:41.000000000 +0100
@@ -284,7 +284,6 @@ static char *
read_sf (st_parameter_dt *dtp, int * length)
{
static char *empty_string[0];
- char *base;
int q, q2;
int n, lorig, seen_comma;
@@ -302,9 +301,6 @@ read_sf (st_parameter_dt *dtp, int * len
/* Read data into format buffer and scan through it. */
lorig = *length;
- base = fbuf_getptr (dtp->u.p.current_unit);
- if (base == NULL)
- return NULL;
while (n < *length)
{
@@ -396,7 +392,12 @@ read_sf (st_parameter_dt *dtp, int * len
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
dtp->u.p.size_used += (GFC_IO_INT) n;
- return base;
+ /* We can't call fbuf_getptr before the loop doing fbuf_getc, because
+ fbuf_getc might reallocate the buffer. So return current pointer
+ minus all the advances, which is n plus up to two characters
+ of newline or comma. */
+ return fbuf_getptr (dtp->u.p.current_unit)
+ - n - dtp->u.p.sf_seen_eor - seen_comma;
}
--- gcc/testsuite/gfortran.dg/pr47878.f90.jj 2011-02-24 18:12:03.000000000 +0100
+++ gcc/testsuite/gfortran.dg/pr47878.f90 2011-02-24 18:12:59.000000000 +0100
@@ -0,0 +1,10 @@
+! PR fortran/47878
+! { dg-do run }
+ integer :: a(5)
+ open (99, recl = 40)
+ write (99, '(5i3)') 1, 2, 3
+ rewind (99)
+ read (99, '(5i3)') a
+ if (any (a.ne.(/1, 2, 3, 0, 0/))) call abort
+ close (99, status = 'delete')
+end
Jakub