https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116388
Bug ID: 116388
Summary: [13/14/15 regression] Finalizer called on
uninitialized components of intent(out) argument
Product: gcc
Version: 13.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: trnka at scm dot com
Target Milestone: ---
Created attachment 58935
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58935&action=edit
testcase illustrating this issue
This feels potentially related to PR115070 but it is probably not an exact
duplicate; the proposed fix in PR115070 comment 9 does not fix this issue on
current master branch.
The attached testcase contains a type like this:
type, public :: AType
type(C_ptr) :: cptr = C_null_ptr
logical :: cptr_invalid = .true.
integer, allocatable :: x(:)
contains
final :: FinalizerA
end type
…
impure elemental subroutine FinalizerA(self)
type(AType), intent(inout) :: self
if (.not. self%cptr_invalid) write(*,*) "A:", self%cptr
end subroutine
Nothing in the program ever sets "cptr_invalid" to .false., so "A:" should
never be printed. However, compiling the testcase with gfortran 13.x and up
produces a program which often prints "A: somerandomvalue" once. Looking at the
tree dump, this is because the __final for CType creates a temporary
"comp_byte_stride", which is only partially initialized (so the components of
AType apart from x aren't initialized) but then calls FinalizerA on the whole a
component.
integer(kind=4) __final_finalizertestmodule_Ctype (struct array15_ctype &
restrict array, integer(kind=8) byte_stride, logical(kind=1) fini_coarray)
{
struct btype comp_byte_stride;
…
try
{
comp_byte_stride.a.x.data = 0B;
// no other components of comp_byte_stride are initialized here
…
finally
{
__builtin_free ((void *) strides);
__builtin_free ((void *) sizes);
desc.6.dtype = {.elem_len=80, .version=0, .rank=0, .type=5};
desc.6.data = (void * restrict) &comp_byte_stride.a;
desc.6.span = (integer(kind=8)) desc.6.dtype.elem_len;
__final_finalizertestmodule_Atype (&desc.6, 80, 1);
Accessing uninitialized data at runtime is also confirmed using valgrind
--tool=memcheck.
"comp_byte_stride" was introduced by the following commit which went into 13.x.
GCC 12 and older seems to be unaffected by this issue.
commit d7caf313525a46f200d7f5db1ba893f853774aee
Author: Paul Thomas <[email protected]>
Date: Sat Mar 18 07:56:23 2023 +0000
Fortran: Fix bugs and missing features in finalization [PR37336]
2023-03-18 Paul Thomas <[email protected]>
(BType in the testcase seems to be superfluous but removing it and putting
AType straight into CType masks the issue somewhat, because the uninitialized
data then happens to have the right value so that A: is never printed. However,
the bug still seems to be there in the tree dump even without BType.)