The fix for

> PR fortran/95104 - Segfault on a legal WAIT statement
>
> Referencing a unit in a WAIT statement that has not been opened before
> resulted in a NULL pointer dereference.  Check for this condition.
>
> 2020-05-26  Harald Anlauf  <anl...@gmx.de>
>
> libgfortran/
>       PR libfortran/95104
>       * io/transfer.c (st_wait_async): Do not dereference NULL pointer.
>
> gcc/testsuite/
>       PR libfortran/95104
>       * gfortran.dg/pr95104.f90: New test.
>
> Co-Authored-By: Steven G. Kargl  <ka...@gcc.gnu.org>

did uncover a latent issue with regard to unit locking that was introduced in 
the
context of asynchronous I/O in libgfortran.  This was reported by Rainer Orth, 
see

  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95104#c13

I can reproduce this when compiling/linking with -fopenmp.

There are two possible fixes for this:

(1) guard the call to unlock_unit by:

diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index cd51679ff46..296be0711a2 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -4508,7 +4508,8 @@ st_wait_async (st_parameter_wait *wtp)
        async_wait (&(wtp->common), u->au);
     }

-  unlock_unit (u);
+  if (u)
+    unlock_unit (u);
 }



(2) in unlock_unit():

diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 0030d7e8701..a3b0656cb90 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -767,9 +767,12 @@ close_unit_1 (gfc_unit *u, int locked)
 void
 unlock_unit (gfc_unit *u)
 {
-  NOTE ("unlock_unit = %d", u->unit_number);
-  UNLOCK (&u->lock);
-  NOTE ("unlock_unit done");
+  if (u)
+    {
+      NOTE ("unlock_unit = %d", u->unit_number);
+      UNLOCK (&u->lock);
+      NOTE ("unlock_unit done");
+    }
 }

 /* close_unit()-- Close a unit.  The stream is closed, and any memory


Does anybody prefer one over the other, or just commit both (which might be
preferable to catch other unguarded cases)?

Thanks,
Harald

Reply via email to