diff options
author | jvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-12-16 19:59:14 +0000 |
---|---|---|
committer | jvdelisle <jvdelisle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-12-16 19:59:14 +0000 |
commit | eba7d7c8260dcbf5b1dbb58378c6c07af345064a (patch) | |
tree | 5c08410bfcb6a2678ddb62a6443a48a2c3e1cc7e /libgfortran | |
parent | 22609e1632283b05e026b6ffaeebc0999b9ddd5f (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/ChangeLog | 18 | ||||
-rw-r--r-- | libgfortran/io/inquire.c | 5 | ||||
-rw-r--r-- | libgfortran/io/transfer.c | 17 | ||||
-rw-r--r-- | libgfortran/io/unit.c | 9 | ||||
-rw-r--r-- | libgfortran/io/unix.c | 4 |
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; } |