summaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorjvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4>2017-12-16 19:59:14 +0000
committerjvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4>2017-12-16 19:59:14 +0000
commiteba7d7c8260dcbf5b1dbb58378c6c07af345064a (patch)
tree5c08410bfcb6a2678ddb62a6443a48a2c3e1cc7e /libgfortran
parent22609e1632283b05e026b6ffaeebc0999b9ddd5f (diff)
2017-12-16 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Backport from trunk PR libgfortran/78549 * io/inquire.c (inquire_via_unit): Adjust test for existence for pre-connected internal units. * io/transfer.c (finalize_transfer): When done with a transfer to internal units, free the format buffer and close the stream. (st_read_done): Delete freeing the stream, now handled using sclose in finalize_transfer. (st_write_done): Likewise. * io/unit.c (get_unit): Return NULL for special reserved unit numbers, signifying not accessible to the user. (init_units): Insert the two special internal units into the unit treap. This makes these unit structures available without further allocations for later use by internal unit I/O. These units are automatically deleted by normal program termination. * io/unix.c (mem_close): Add a guard check to protect from double free. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@255751 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog18
-rw-r--r--libgfortran/io/inquire.c5
-rw-r--r--libgfortran/io/transfer.c17
-rw-r--r--libgfortran/io/unit.c9
-rw-r--r--libgfortran/io/unix.c4
5 files changed, 45 insertions, 8 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 986b2b0a31e3..83147ac776bc 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,21 @@
+2017-12-16 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from trunk
+ PR libgfortran/78549
+ * io/inquire.c (inquire_via_unit): Adjust test for existence for
+ pre-connected internal units.
+ * io/transfer.c (finalize_transfer): When done with a transfer
+ to internal units, free the format buffer and close the stream.
+ (st_read_done): Delete freeing the stream, now handled using
+ sclose in finalize_transfer. (st_write_done): Likewise.
+ * io/unit.c (get_unit): Return NULL for special reserved unit
+ numbers, signifying not accessible to the user.
+ (init_units): Insert the two special internal units into the
+ unit treap. This makes these unit structures available without
+ further allocations for later use by internal unit I/O. These
+ units are automatically deleted by normal program termination.
+ * io/unix.c (mem_close): Add a guard check to protect from double free.
+
2017-12-03 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Backport from trunk
diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c
index 4cf87d339a7f..da5b674a8916 100644
--- a/libgfortran/io/inquire.c
+++ b/libgfortran/io/inquire.c
@@ -47,7 +47,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit *u)
generate_error (&iqp->common, LIBERROR_INQUIRE_INTERNAL_UNIT, NULL);
if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
- *iqp->exist = (u != NULL) || (iqp->common.unit >= 0);
+ *iqp->exist = (u != NULL &&
+ iqp->common.unit != GFC_INTERNAL_UNIT &&
+ iqp->common.unit != GFC_INTERNAL_UNIT4)
+ || (iqp->common.unit >= 0);
if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
*iqp->opened = (u != NULL);
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 316d3283669a..7d270fb8b369 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -3984,6 +3984,19 @@ finalize_transfer (st_parameter_dt *dtp)
next_record (dtp, 1);
done:
+
+ if (dtp->u.p.unit_is_internal)
+ {
+ fbuf_destroy (dtp->u.p.current_unit);
+ if (dtp->u.p.current_unit
+ && (dtp->u.p.current_unit->child_dtio == 0)
+ && dtp->u.p.current_unit->s)
+ {
+ sclose (dtp->u.p.current_unit->s);
+ dtp->u.p.current_unit->s = NULL;
+ }
+ }
+
#ifdef HAVE_USELOCALE
if (dtp->u.p.old_locale != (locale_t) 0)
{
@@ -4093,8 +4106,6 @@ st_read_done (st_parameter_dt *dtp)
{
free (dtp->u.p.current_unit->filename);
dtp->u.p.current_unit->filename = NULL;
- free (dtp->u.p.current_unit->s);
- dtp->u.p.current_unit->s = NULL;
if (dtp->u.p.current_unit->ls)
free (dtp->u.p.current_unit->ls);
dtp->u.p.current_unit->ls = NULL;
@@ -4164,8 +4175,6 @@ st_write_done (st_parameter_dt *dtp)
{
free (dtp->u.p.current_unit->filename);
dtp->u.p.current_unit->filename = NULL;
- free (dtp->u.p.current_unit->s);
- dtp->u.p.current_unit->s = NULL;
if (dtp->u.p.current_unit->ls)
free (dtp->u.p.current_unit->ls);
dtp->u.p.current_unit->ls = NULL;
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 4b49b26311c5..769c7cc1da24 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -563,7 +563,11 @@ get_unit (st_parameter_dt *dtp, int do_create)
is not allowed, such units must be created with
OPEN(NEWUNIT=...). */
if (dtp->common.unit < 0)
- return get_gfc_unit (dtp->common.unit, 0);
+ {
+ if (dtp->common.unit > NEWUNIT_START) /* Reserved units. */
+ return NULL;
+ return get_gfc_unit (dtp->common.unit, 0);
+ }
return get_gfc_unit (dtp->common.unit, do_create);
}
@@ -683,6 +687,9 @@ init_units (void)
__gthread_mutex_unlock (&u->lock);
}
+ /* The default internal units. */
+ u = insert_unit (GFC_INTERNAL_UNIT);
+ u = insert_unit (GFC_INTERNAL_UNIT4);
/* Calculate the maximum file offset in a portable manner.
max will be the largest signed number for the type gfc_offset.
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index c76b427387ad..20320776e5fd 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -959,8 +959,8 @@ mem_flush (unix_stream *s __attribute__ ((unused)))
static int
mem_close (unix_stream *s)
{
- free (s);
-
+ if (s)
+ free (s);
return 0;
}