]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fortran: Fix UB in transfer_expr [PR124450]
authorJakub Jelinek <jakub@redhat.com>
Thu, 12 Mar 2026 11:39:43 +0000 (12:39 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 12 Mar 2026 11:39:43 +0000 (12:39 +0100)
trans-io.cc (transfer_array_component) calls transfer_expr with
NULL code:
  transfer_expr (&se, &cm->ts, tmp, NULL, NULL_TREE);
I'm surprised it doesn't ICE in other spots that dereference
code->whatever but each one is guarded with some condition
that perhaps don't trigger in that case for some reason.
Anyway, the &code->loc case does trigger, it doesn't ICE, but
it is undefined behavior in the compiler when code is NULL,
and we'd crash if the where argument of 3*sizeof(void*) is
dereferenced.  Code I've checked can handle NULL where though.

2026-03-12  Jakub Jelinek  <jakub@redhat.com>

PR fortran/124450
* trans-io.cc (transfer_expr): If code is NULL, call
transfer_array_component with NULL where argument rather than
&code->loc.

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

gcc/fortran/trans-io.cc
gcc/testsuite/gfortran.dg/pr124450.f90 [new file with mode: 0644]

index 23ab1e599f3a7d904573090c2617c0bdb69b1182..a18b2bca6aa66bd05a570b15924189ff14105d5b 100644 (file)
@@ -2513,7 +2513,9 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
 
                  if (c->attr.dimension)
                    {
-                     tmp = transfer_array_component (tmp, c, & code->loc);
+                     tmp = transfer_array_component (tmp, c,
+                                                     code ? &code->loc
+                                                     : NULL);
                      gfc_add_expr_to_block (&se->pre, tmp);
                    }
                  else
diff --git a/gcc/testsuite/gfortran.dg/pr124450.f90 b/gcc/testsuite/gfortran.dg/pr124450.f90
new file mode 100644 (file)
index 0000000..b6d9abc
--- /dev/null
@@ -0,0 +1,14 @@
+! PR fortran/124450
+! { dg-do compile }
+
+  type ta
+    integer(kind=4) :: a(1)
+    integer(kind=4) :: b(1)
+  end type ta
+  type tb
+    type(ta) :: c(1) = ta(1, 2)
+  end type tb
+  type(tb) :: e = tb(ta(3, 4))
+
+  print *, e
+end