https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128419
Bug ID: 128419
Summary: [17 regression] bounds incorrectly set for ALLOCATE
with an array subreference as SOURCE
Product: gcc
Version: 17.0
URL: https://gcc.sashiko.dev/#/patchset/20261021092953.3158
4-1-morin-mikael%40orange.fr
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: mikael at gcc dot gnu.org
Target Milestone: ---
This is based on the AI review of the PR128033 fix (AKA r17-5758) at:
https://gcc.sashiko.dev/#/patchset/20261021092953.31584-1-morin-mikael%40orange.fr
More exactly, the testcase combines item 1 first bullet and item 3
program prog
implicit none
integer, parameter :: n = 5
type :: t1
integer :: c1, c2
end type
type(t1), allocatable :: a(:)
integer :: i
allocate(a(3:n+2), source=[ (t1(2*i*i+1, 3*i+2), i=1,n) ])
call sub(a)
contains
subroutine sub(x)
type(t1), allocatable :: x(:)
class(*), pointer :: p(:)
allocate(p, source=x%c1)
if (any(lbound(a) /= 3)) error stop 11
if (any(ubound(a) /= 7)) error stop 12
if (any(lbound(x) /= 3)) error stop 21
if (any(ubound(x) /= 7)) error stop 22
if (any(lbound(p) /= 1)) error stop 31
if (any(ubound(p) /= 5)) error stop 32
end subroutine
end program
This examples fails at runtime with ERROR STOP 31.
gfortran-16 executes it without error.
Citing the URL above:
> Removing the gfc_get_parentheses wrapper here causes wrong-code and runtime
> heap buffer overflows when an array is allocated without an explicit shape
> specification from a non-character subreference array variable in SOURCE= or
> MOLD= (for example, allocate(xx, source=cmp%re), allocate(aa, source=x%c),
> or allocate(pp, source=cc%rr%re)).
> With this change, gfc_trans_allocate takes the EXPR_VARIABLE path for
> subreference arrays and calls gfc_conv_expr_descriptor (&se, code->expr3)
> with a default-initialized gfc_se (where se.direct_byref == 0 and
> se.force_no_tmp == 0) while leaving e3_has_nodescriptor false:
> 1. Inside gfc_conv_expr_descriptor (gcc/fortran/trans-array.cc),
> subref_array_target is false for expr->ts.type != BT_CHARACTER when both
> se->direct_byref and se->force_no_tmp are false, and
> gfc_ref_needs_temporary_p returns false for REF_COMPONENT and
> REF_INQUIRY.
> - If the base array is descriptor-backed (allocatable, pointer, or
> assumed-shape) and its array reference is AR_FULL followed by
> REF_COMPONENT or REF_INQUIRY, full remains 1 and
> gfc_conv_expr_descriptor returns the parent derived-type or complex
> array's descriptor directly in se.expr.
(...)
> 3. In addition, in Fortran (F2018 9.5.3.3.2 / 16.9.109), a whole array
> followed by a component or complex-part inquiry reference (such as x%c or
> cmp%re where x or cmp has non-unit lower bounds like 2:4) is an array
> section with lower bound 1. Because full == 1 returns the parent
> descriptor directly, full == 0 skips lower-bound normalization when
> info->ref->u.ar.type == AR_FULL, and e3_has_nodescriptor is false,
> gfc_array_init_size copies the parent array's non-unit lower and upper
> bounds (2:4) into the allocated array instead of 1:3.