Skip to content

Commit b5a3b87

Browse files
author
Jerry DeLisle
committed
fortran: [PR125535] wrong-code for implied-do with allocatable-component
When a nested implied-do array constructor called a transformational intrinsic (e.g. RESHAPE) whose result type has allocatable components, the argument temporaries were freed before the result's allocatable components were deep-copied, causing a heap-use-after-free and wrong runtime values. Transformational library functions such as RESHAPE do a shallow byte-copy of the source array into the result, so the result's component pointers alias those of the argument temporaries. Freeing the temporaries first and then copying yielded use-after-free. Move gfc_add_block_to_block (&se->pre, &post) to after the deep-copy loop, so that the result's allocatable components are copied while the source storage is still live. Assisted by: Claude Sonnet 4.6 PR fortran/125535 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_conv_procedure_call): Move post block append to after the deep copy of allocatable components for transformational intrinsics, so that argument temporaries are not freed before the result components are copied. gcc/testsuite/ChangeLog: * gfortran.dg/implied_do_alloc_comp_1.f90: New test.
1 parent 81a0bec commit b5a3b87

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

gcc/fortran/trans-expr.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9069,12 +9069,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
90699069
/* Follow the function call with the argument post block. */
90709070
if (byref)
90719071
{
9072-
gfc_add_block_to_block (&se->pre, &post);
9073-
90749072
/* Transformational functions of derived types with allocatable
9075-
components must have the result allocatable components copied when the
9076-
argument is actually given. This is unnecessry for REDUCE because the
9077-
wrapper for the OPERATION function takes care of this. */
9073+
components must have the result allocatable components copied
9074+
BEFORE the argument post block is appended. Copying the result
9075+
first, then freeing the argument, gives the correct order. */
90789076
arg = expr->value.function.actual;
90799077
if (result && arg && expr->rank
90809078
&& isym && isym->transformational
@@ -9102,6 +9100,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
91029100
NULL, GFC_CAF_COARRAY_NOCOARRAY);
91039101
gfc_add_expr_to_block (&se->pre, tmp);
91049102
}
9103+
9104+
gfc_add_block_to_block (&se->pre, &post);
91059105
}
91069106
else
91079107
{
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
! { dg-do run }
2+
! Test that a nested implied-do array constructor with a derived-type
3+
! constructor whose argument uses an outer loop variable produces correct
4+
! results when the derived type has an allocatable component.
5+
!
6+
! PR fortran/125535
7+
8+
module m
9+
implicit none
10+
type :: t
11+
real, allocatable :: v(:)
12+
end type
13+
contains
14+
pure function make(x) result(r)
15+
real, intent(in) :: x(:)
16+
type(t) :: r
17+
r%v = x
18+
end function
19+
end module
20+
21+
program implied_do_alloc_comp
22+
use m
23+
implicit none
24+
integer, parameter :: n=3, k=2
25+
type(t), allocatable :: a(:,:)
26+
real :: h(k, n)
27+
integer :: i, j
28+
29+
h(1,:) = [10., 20., 30.]
30+
h(2,:) = [11., 21., 31.]
31+
32+
! Nested implied-do where inner DT constructor uses outer variable i.
33+
! Without the fix this produces heap-use-after-free and wrong values.
34+
a = reshape([([(make(h(:,i)), j=1,1)], i=1,n)], [1,n])
35+
36+
if (any(a(1,1)%v /= h(:,1))) stop 1
37+
if (any(a(1,2)%v /= h(:,2))) stop 2
38+
if (any(a(1,3)%v /= h(:,3))) stop 3
39+
end program

0 commit comments

Comments
 (0)