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 ICE on write without io-unit (PR fortran/40839)


Hi!

gfortran ICEs when io-unit isn't specified for data transfer stmt.
The standard says that io-unit must be specified, io.c resolving wasn't
checking that and even before that resolving it could dereference the NULL
current_dt->io_unit.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux.
Ok for trunk?  What about 4.4?

2009-07-23  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/40839
	* io.c (gfc_resolve_dt): Add LOC argument.  Fail if
	dt->io_unit is NULL.  Return FAILURE after issuing error about
	negative UNIT number.
	(match_io_element): Don't segfault if current_dt->io_unit is NULL.
	* gfortran.h (gfc_resolve_dt): Adjust prototype.
	* resolve.c (resolve_code): Adjust caller.

	* gfortran.dg/pr40839.f90: New test.

--- gcc/fortran/resolve.c.jj	2009-07-20 20:41:43.000000000 +0200
+++ gcc/fortran/resolve.c	2009-07-23 18:20:27.000000000 +0200
@@ -7119,7 +7119,7 @@ resolve_code (gfc_code *code, gfc_namesp
 
 	case EXEC_READ:
 	case EXEC_WRITE:
-	  if (gfc_resolve_dt (code->ext.dt) == FAILURE)
+	  if (gfc_resolve_dt (code->ext.dt, &code->loc) == FAILURE)
 	    break;
 
 	  resolve_branch (code->ext.dt->err, code);
--- gcc/fortran/io.c.jj	2009-06-08 11:53:53.000000000 +0200
+++ gcc/fortran/io.c	2009-07-23 18:20:07.000000000 +0200
@@ -2555,7 +2555,7 @@ gfc_free_dt (gfc_dt *dt)
 /* Resolve everything in a gfc_dt structure.  */
 
 gfc_try
-gfc_resolve_dt (gfc_dt *dt)
+gfc_resolve_dt (gfc_dt *dt, locus *loc)
 {
   gfc_expr *e;
 
@@ -2576,6 +2576,12 @@ gfc_resolve_dt (gfc_dt *dt)
   RESOLVE_TAG (&tag_e_async, dt->asynchronous);
 
   e = dt->io_unit;
+  if (e == NULL)
+    {
+      gfc_error ("UNIT not specified at %L", loc);
+      return FAILURE;
+    }
+
   if (gfc_resolve_expr (e) == SUCCESS
       && (e->ts.type != BT_INTEGER
 	  && (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_VARIABLE)))
@@ -2635,6 +2641,7 @@ gfc_resolve_dt (gfc_dt *dt)
       && mpz_sgn (e->value.integer) < 0)
     {
       gfc_error ("UNIT number in statement at %L must be non-negative", &e->where);
+      return FAILURE;
     }
 
   if (dt->extra_comma
@@ -2857,6 +2864,7 @@ match_io_element (io_kind k, gfc_code **
 
 	if (gfc_pure (NULL)
 	    && gfc_impure_variable (expr->symtree->n.sym)
+	    && current_dt->io_unit
 	    && current_dt->io_unit->ts.type == BT_CHARACTER)
 	  {
 	    gfc_error ("Cannot read to variable '%s' in PURE procedure at %C",
@@ -2870,7 +2878,8 @@ match_io_element (io_kind k, gfc_code **
 	break;
 
       case M_WRITE:
-	if (current_dt->io_unit->ts.type == BT_CHARACTER
+	if (current_dt->io_unit
+	    && current_dt->io_unit->ts.type == BT_CHARACTER
 	    && gfc_pure (NULL)
 	    && current_dt->io_unit->expr_type == EXPR_VARIABLE
 	    && gfc_impure_variable (current_dt->io_unit->symtree->n.sym))
--- gcc/fortran/gfortran.h.jj	2009-07-20 20:41:43.000000000 +0200
+++ gcc/fortran/gfortran.h	2009-07-23 18:19:41.000000000 +0200
@@ -2637,7 +2637,7 @@ gfc_try gfc_resolve_filepos (gfc_filepos
 void gfc_free_inquire (gfc_inquire *);
 gfc_try gfc_resolve_inquire (gfc_inquire *);
 void gfc_free_dt (gfc_dt *);
-gfc_try gfc_resolve_dt (gfc_dt *);
+gfc_try gfc_resolve_dt (gfc_dt *, locus *);
 void gfc_free_wait (gfc_wait *);
 gfc_try gfc_resolve_wait (gfc_wait *);
 
--- gcc/testsuite/gfortran.dg/pr40839.f90.jj	2009-07-23 18:24:29.000000000 +0200
+++ gcc/testsuite/gfortran.dg/pr40839.f90	2009-07-23 18:23:52.000000000 +0200
@@ -0,0 +1,5 @@
+! PR fortran/40839
+! { dg-do compile }
+write(fmt='(a)'), 'abc'         ! { dg-error "UNIT not specified" }
+write(fmt='()')                 ! { dg-error "UNIT not specified" }
+end

	Jakub


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