This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[PATCH] Fix libgfortran read_sf (PR fortran/47878)


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


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