This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[PATCH] Fix up trans_array_constructor UB (PR fortran/67496)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: fortran at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 17 Aug 2016 20:56:48 +0200
- Subject: [PATCH] Fix up trans_array_constructor UB (PR fortran/67496)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The bug here is that it dereferences expr->ts.u.cl if non-NULL
unconditionally, no matter what expr->ts.type is.
But, ts.u is an union, where ts.u.cl is only valid for BT_CHARACTER,
ts.u.derived for BT_DERIVED etc. ts.u.pad (an int rather than pointer)
for BT_HOLLERITH? and unused in others.
So, as on the testcase, where expr->ts.type == BT_DERIVED,
expr->ts.u.derived points to a gfc_symbol structure and thus dereferencing
ts.u.cl means reading gfc_symbol bytes as if it is gfc_charlen.
length_from_typespec is a bool, which can be only false or true, but
on the testcase happens to point to a byte in gfc_symbol that has some other
value (60 in my case), so the read is undefined behavior.
Fixed by doing it only when ts.u.cl is valid. Bootstrapped/regtested on
x86_64-linux and i686-linux, ok for trunk?
2016-08-17 Jakub Jelinek <jakub@redhat.com>
PR fortran/67496
* trans-array.c (trans_array_constructor): Load
expr->ts.u.cl->length_from_typespec only if expr->ts.type is
BT_CHARACTER.
* gfortran.dg/pr67496.f90: New test.
--- gcc/fortran/trans-array.c.jj 2016-08-12 17:33:44.000000000 +0200
+++ gcc/fortran/trans-array.c 2016-08-17 15:20:44.248509114 +0200
@@ -2239,7 +2239,8 @@ trans_array_constructor (gfc_ss * ss, lo
/* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
typespec was given for the array constructor. */
- typespec_chararray_ctor = (expr->ts.u.cl
+ typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
+ && expr->ts.u.cl
&& expr->ts.u.cl->length_from_typespec);
if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
--- gcc/testsuite/gfortran.dg/pr67496.f90.jj 2016-08-17 15:28:45.445223929 +0200
+++ gcc/testsuite/gfortran.dg/pr67496.f90 2016-08-17 15:28:09.000000000 +0200
@@ -0,0 +1,12 @@
+! PR fortran/67496
+! { dg-do compile }
+
+ type :: a
+ end type a
+ type :: b
+ type (a) :: j(1)
+ end type b
+ type(a) :: x
+ type(b) :: y
+ y = b((/x/))
+end
Jakub