See the attached patch.
This is a followup to the PR128357 patch fixing the additional case identified
by Harald. It turns out to be not too difficult.
Regression tested on x86_64.
OK for mainline?
Regards,
Jerry
---
fortran: [PR128509] Double free with a parenthesized array constructor
The allocatable components of the elements of a parenthesized array
constructor were freed after the call while still shared with the
variables in the constructor, which then freed them again. The
temporary for the parenthesized expression was a shallow copy of the
constructor's temporary, because only a variable or a constructor got a
deep copy, and for an elemental procedure the parentheses hid the
variables from expr_may_alias_variables. Treat a parenthesized array
constructor like the constructor in both places.
Assisted-by: Claude Opus 5.5
PR fortran/128509
gcc/fortran/ChangeLog:
* trans-array.cc (gfc_conv_expr_descriptor): Copy the temporary for
a parenthesized array constructor deeply, as for the constructor.
* trans-expr.cc (expr_may_alias_variables): Look through the
parentheses around an array constructor.
gcc/testsuite/ChangeLog:
* gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90: New test.
---From b1f4b3f5f6e53dc82e64fc5f1653899ba3b05a10 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Fri, 6 Nov 2026 10:39:39 -0800
Subject: [PATCH] fortran: [PR128509] Double free with a parenthesized array
constructor
The allocatable components of the elements of a parenthesized array
constructor were freed after the call while still shared with the
variables in the constructor, which then freed them again. The
temporary for the parenthesized expression was a shallow copy of the
constructor's temporary, because only a variable or a constructor got a
deep copy, and for an elemental procedure the parentheses hid the
variables from expr_may_alias_variables. Treat a parenthesized array
constructor like the constructor in both places.
Assisted-by: Claude Opus 5.5
PR fortran/128509
gcc/fortran/ChangeLog:
* trans-array.cc (gfc_conv_expr_descriptor): Copy the temporary for
a parenthesized array constructor deeply, as for the constructor.
* trans-expr.cc (expr_may_alias_variables): Look through the
parentheses around an array constructor.
gcc/testsuite/ChangeLog:
* gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90: New test.
---
gcc/fortran/trans-array.cc | 10 ++++--
gcc/fortran/trans-expr.cc | 5 +++
.../asan/paren_array_ctor_alloc_comp_1.f90 | 36 +++++++++++++++++++
3 files changed, 49 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 2a95784d860..48e8634b246 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -8514,9 +8514,15 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
lse.string_length = rse.string_length;
+ /* A parenthesized constructor is copied like the constructor. */
+ gfc_expr *src = expr;
+ if (src->expr_type == EXPR_OP
+ && src->value.op.op == INTRINSIC_PARENTHESES
+ && src->value.op.op1->expr_type == EXPR_ARRAY)
+ src = src->value.op.op1;
deep_copy = !se->data_not_needed
- && (expr->expr_type == EXPR_VARIABLE
- || expr->expr_type == EXPR_ARRAY);
+ && (src->expr_type == EXPR_VARIABLE
+ || src->expr_type == EXPR_ARRAY);
tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
deep_copy, false);
gfc_add_expr_to_block (&block, tmp);
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 89d9a64de59..4ce442aca1d 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6043,6 +6043,11 @@ expr_may_alias_variables (gfc_expr *e, bool array_may_alias)
{
gfc_constructor *c;
+ if (e->expr_type == EXPR_OP
+ && e->value.op.op == INTRINSIC_PARENTHESES
+ && e->value.op.op1->expr_type == EXPR_ARRAY)
+ e = e->value.op.op1;
+
if (e->expr_type == EXPR_VARIABLE)
return true;
else if (e->expr_type == EXPR_FUNCTION)
diff --git a/gcc/testsuite/gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90 b/gcc/testsuite/gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90
new file mode 100644
index 00000000000..0aa8462ff11
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/asan/paren_array_ctor_alloc_comp_1.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+!
+! PR 128509
+! The components of a parenthesized array constructor of a type with
+! allocatable components were freed after the call while still shared
+! with TA, which then freed them again. Checked under -fsanitize=address.
+
+module m
+ implicit none
+ type :: t
+ integer, allocatable :: v(:)
+ end type
+contains
+ subroutine s (x)
+ type(t), intent(in) :: x(:)
+ if (x(2)%v(2) /= 2) stop 1
+ end subroutine
+ elemental subroutine se (x)
+ type(t), intent(in) :: x
+ end subroutine
+ subroutine work ()
+ type(t) :: ta(2)
+
+ ta(1) = t ([1])
+ ta(2) = t ([2, 2])
+ call s (([ta]))
+ call se (([ta]))
+ if (any (ta(2)%v /= 2)) stop 2
+ end subroutine
+end module
+
+program p
+ use m
+ implicit none
+ call work ()
+end program
--
2.56.0