Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Zero size computed for derived types with forward pointers to other derived types #64973

Closed
rofirrim opened this issue Aug 25, 2023 · 4 comments
Labels
bug Indicates an unexpected problem or unintended behavior flang:frontend

Comments

@rofirrim
Copy link
Collaborator

Hi,

Consider the following testcase:

! t3.f90
program main
  implicit none

  type t1
    type(t2), pointer :: b
  end type t1

  type, extends(t1) :: t2
    type(t1), pointer :: a
  end type t2

  type(t2), pointer :: x
  allocate(x)
end program main

If we check the size of t2, flang has computed 0 (field sizeinbytes)

$ flang-new -fc1 -fdebug-dump-symbols t3.f90 | grep -o "\.dt.t[12].*sizeinbytes=[^,]\+"
.dt.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t1,sizeinbytes=40_8
.dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t2,sizeinbytes=0_8

If we change the type of the field t1.b to be, say, integer as in

  type t1
    integer, pointer :: b
  end type t1

We get something that is nonzero for t2 (I assume the size is now correct).

.dt.t1, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t1,sizeinbytes=24_8
.dt.t2, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t2,sizeinbytes=64_8

Original observation

For the sake of context, we found this issue in a code that uses polymorphic types. In that case the size in bytes stored in the type descriptor is ultimately used to initialise the amount of memory allocated by allocate.

Below is the original motivating example:

! t.f90
program testcase

  implicit none

  integer(4), parameter :: ip = 4
  integer(4), parameter :: rp = 8

  integer(ip), parameter :: element_max = 110

  type :: quadrature
     integer(ip)          :: ndime
     integer(ip)          :: ngaus
     integer(ip)          :: type
     integer(ip)          :: topo
     real(rp),    pointer :: weigp(:)
     real(rp),    pointer :: posgp(:,:)
     integer(8)           :: memor(2)
  end type quadrature

  type mesh_type_basic
     class(bmsh_type_basic),    pointer :: boundary
     type(quadrature)                   :: quad(element_max)
  end type mesh_type_basic

  type, extends(mesh_type_basic) :: bmsh_type_basic
     class(mesh_type_basic),    pointer :: mesh
  end type bmsh_type_basic

  class(bmsh_type_basic),    pointer :: boundary

  allocate(boundary)  ! (A)
  print *, 'Finishing'
end program testcase

This program will typically crash. The allocate statement at (A) calls PointerNullifyDerived to establish the descriptor of boundary. But the associated type descriptor for bmsh_type_basic says its size is zero. Then PointerAllocate will use that size to allocate the storage for the derived type. Because it is zero it will start clobbering the heap because the buffer we allocated was not accessible.

The wrong malloc can be seen in the debugger

$ flang-new -flang-experimental-polymorphism -c -g -o t.o t.f90
$ flang-new -flang-experimental-polymorphism -o t -g  t.o
$ gdb --quiet --args ./t
Reading symbols from ./t...
(gdb) b _QQmain
Breakpoint 1 at 0x84e0: file t.f90, line 1.
(gdb) r
Starting program: /home/rferrer/tmp/t 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, _QQmain () at t.f90:1
1	! t.f90
(gdb) b malloc
Breakpoint 2 at 0x7ffff7d48120: file ./malloc/malloc.c, line 3287.
(gdb) c
Continuing.

Breakpoint 2, __GI___libc_malloc (bytes=0) at ./malloc/malloc.c:3287
3287	./malloc/malloc.c: No such file or directory.
(gdb) bt
#0  __GI___libc_malloc (bytes=0) at ./malloc/malloc.c:3287
#1  0x00005555555d3d5e in Fortran::runtime::Descriptor::Allocate (this=0x5555556821e0 <_QFEboundary>) at /home/rferrer/fio/upstream/llvm-src/flang/runtime/descriptor.cpp:145
#2  0x00005555555c1c7c in _FortranAPointerAllocate (pointer=..., hasStat=false, errMsg=0x0, sourceFile=0x55555561c0d0 <_QQcl.d5bb05b2624fe90fadde0ebdef80c20d> "/home/rferrer/tmp/t.f90", 
    sourceLine=32) at /home/rferrer/fio/upstream/llvm-src/flang/runtime/pointer.cpp:141
#3  0x000055555555c5be in _QQmain () at t.f90:32
#4  0x000055555555c639 in main (argc=1, argv=0x7fffffffe2f8, envp=0x7fffffffe308) at /home/rferrer/fio/upstream/llvm-src/flang/runtime/FortranMain/Fortran_main.c:20

Running under valgrind detects the problem

==2021463== Invalid write of size 8
==2021463==    at 0x18737C: Fortran::ISO::EstablishDescriptor(Fortran::ISO::Fortran_2018::CFI_cdesc_t*, void*, unsigned char, signed char, unsigned long, unsigned char, long const*) (llvm-src/flang/runtime/ISO_Fortran_util.h:83)
==2021463==    by 0x1870D3: Fortran::runtime::Descriptor::Establish(Fortran::runtime::TypeCode, unsigned long, void*, int, long const*, unsigned char, bool) (llvm-src/flang/runtime/descriptor.cpp:41)
==2021463==    by 0x1879AE: Fortran::runtime::Descriptor::Establish(Fortran::runtime::typeInfo::DerivedType const&, void*, int, long const*, unsigned char) (llvm-src/flang/runtime/descriptor.cpp:89)
==2021463==    by 0x17909F: Fortran::runtime::typeInfo::Component::EstablishDescriptor(Fortran::runtime::Descriptor&, Fortran::runtime::Descriptor const&, Fortran::runtime::Terminator&) const (llvm-src/flang/runtime/type-info.cpp:107)
==2021463==    by 0x185CB7: Fortran::runtime::Initialize(Fortran::runtime::Descriptor const&, Fortran::runtime::typeInfo::DerivedType const&, Fortran::runtime::Terminator&, bool, Fortran::runtime::Descriptor const*) (llvm-src/flang/runtime/derived.cpp:69)
==2021463==    by 0x175CFD: _FortranAPointerAllocate (llvm-src/flang/runtime/pointer.cpp:146)
==2021463==    by 0x1105BD: _QQmain (t.f90:32)
==2021463==    by 0x110638: main (llvm-src/flang/runtime/FortranMain/Fortran_main.c:20)
==2021463==  Address 0x4b7b040 is 0 bytes after a block of size 0 alloc'd
==2021463==    at 0x484880F: malloc (vg_replace_malloc.c:431)
==2021463==    by 0x187D5D: Fortran::runtime::Descriptor::Allocate() (llvm-src/flang/runtime/descriptor.cpp:145)
==2021463==    by 0x175C7B: _FortranAPointerAllocate (llvm-src/flang/runtime/pointer.cpp:141)
==2021463==    by 0x1105BD: _QQmain (t.f90:32)
==2021463==    by 0x110638: main (llvm-src/flang/runtime/FortranMain/Fortran_main.c:20)

The issue does not happen if the variable boundary is a TYPE instead of a CLASS because in this case the type descriptor is not used (i.e. no call to PointerNullifyDerived happens) and the real size is evaluated elsewhere and is non-zero. (Though I'm not 100% sure it is correct, valgrind does not flag any error either in that case so I have no reason to believe it is wrong).

@EugeneZelenko EugeneZelenko added flang Flang issues not falling into any other category and removed new issue labels Aug 25, 2023
@rofirrim
Copy link
Collaborator Author

Tentative patch at https://reviews.llvm.org/D159117

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" flang:frontend and removed flang Flang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Aug 29, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2023

@llvm/issue-subscribers-clang-frontend

@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2023

@llvm/issue-subscribers-flang-frontend

@psteinfeld psteinfeld added the bug Indicates an unexpected problem or unintended behavior label Aug 29, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2023

@llvm/issue-subscribers-bug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior flang:frontend
Projects
None yet
Development

No branches or pull requests

4 participants