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.

Reply via email to