<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/64973>64973</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[flang] Zero size computed for derived types with forward pointers to other derived types
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
rofirrim
</td>
</tr>
</table>
<pre>
Hi,
Consider the following testcase:
```fortran
! 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
```fortran
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:
```fortran
! 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).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUWtty4zbSfhr4pkssEtSBuvCFLFn5XTXJZDLOv7V7owLJJoUMCTAAaFt5-i0AJHW0Vs7OViVTLg8P3Y3ur48AzbTmpUC8J5MHMlndsdZspbpXsuBK8foulfnu_v84oUsSrki48L-XUmieowKzRShkVclXLkowqE3GNJJ4cUhNpqH_KaQyionuKY3AxEExD_19o2SpWA014x0FAK-bimfcgJACD0UCmF2DYKL-1j8gNDGU0DmhS2gkFwYVWGXiBaQ9JYr8mLl74fmXgG8GRa6tqIjQec9v6PlS0eWl2PlS9Fz5K7q-9XSsqmTGjKV9s6TusZV6DtYA8uFKTwW8ImRbzL45V2n-B4IsgExDQy0tXUJRMVHClmnIZN20BnMIgdCk4FjlltIycZHuDGrHMr_o296pYy9wJPAVRkUWwajIMW3LUd7WzUjv6lRWunM8kNkSSoUNjCQQSslkGeQmMGTyEFEyWQWELg5Xj1cuSh9tNE5WZLIk9MGyuaUdZ2Qt-rr4f0sCz4tffnh8trYsZd3wCtVSITOY25e_IMs_i2pn7YkX8Dn9DTPzKAw3O--eeAHP__z5kdAkR8VfMPdOmwMX3JB4cfQ0SbnIuShJvPrp10-fCE28ZwWrkcSrQHjVjo0Zh5vkQHf619Wdnuk-qH417pgo0QWeywJZ-HrRB5aJgpRMQzASUpd6mu3sf2Qa2nQoUdm3TMMQ41fKyYWK0Av5UDG4ZM4_EEo0oGWNZusK3ZYZ4NqWpT9QSSikGnLK-uwJmNZtjfukc8SvkEmlMDOEzoMrWfT3C2U6_vuG8nR8NZYJjf0PfFa85IJVIFON6oUZLo8Ccy19Q9Tsmwv2TAqDb8aa-WrbZGuDbcs1cK1bBC6AQSZz9OHUatTQyGpXS9VseebM1wE8Cf_eNtaDeBLg9AdtpMLc3g95lqPOFG-MVDbs2srwmhmsdnaJ3GabhY6zincCWS1bYazGNdZS7Ya2k0O6s3E9tKFpeBS2D1jJV7uGlSJ7dGppuAVHlIBvrG6qD8wD5-PAMFMcNdArg8GQ9cm4765MsRoP0p83QOIVjD_AojxL8t5avHmPEyusUZhNzd6ciCgKL0wyHfHvLcsVM63CfRk7XQWGfx2TyHl9jb4nK1mrPyDWpdQHyGUjD8gVsorQRPW4AJwW4VfkZWNTNF4MQ8WNrI3Ue9blmYC9qsmRpj27C3NCE3rANnSCUxccualGvd3Yq03KNM8O1swqpu3QmNbHFJeHUVsLmNod8HcF7GD1I81PLLBkhCYHsXXJlIvaHs-gh_PuKfk-dE6NOjf7nPeC2ZboTMmLsjuq66Cex8Uxrhem6IHAgmsrDqHJYfA0igsDhC7cHEJnay64ti2f0Nn59H1Smy51j2db73v6V15V1miesaraQaaY3gbwvMWTIgvaMOM8C8yAG7q9ltMQLKu2z372pv_UVhUvdivfBrtxCrVhacX11lXmg37gZ_8BhWkYwENrfBfQWmbcVf3TLtKNN6desIqynQZu9DDk2HHImSQOdFwcmOYwaHXX9BybkYOLfIMzUrES3bJef2ebUyuAB8yY5eemX89eOrHaMGUgq2SaovJzGsIWWQNpx2QfpG1RoLIted_nXpmdzwywLEOteVphcOxFhFclRWmNqh2b94WAFEEjir4Bu72OrT2375HcJb41qLh1OatG-ylA1zDKYFTaDZIJ5GGD_KgYCcYKsmL2Aso8hdHo95ajgdGIqVJDQOjaeAo7nFkY-11boWTt3wdBjw9Nyjy16ZTC5suX_X70QSH75tITIhvF4VsyxtAmacEr7AyhS6i4QIjOpHUAfrUetSp0KWT5CV1vZY2ErlWBStk6vzZ1Y39DJ2by8LxVyPLOHVZAq-3viqfGvdnkKaBgaYW53Uo6tl8dyVZqc0xX8VQxtXM7VLqueEro-i2ZbqbjUcVF-zYqRetfDDyBlkFEKD0elw4gsaZ3eIEfUy1IHpV40W1GIhLOT8aiQ7y7QDyVTT3cs6Ioilk-TiK6h906r2PrL4JscENMk9mZJ7LhyMdw0XJRvmeTG_o3mx-eNptNxdNs4-Vb84ZdY2fnZTXihVXAy_VX8_cI4ScJus223iqpIOd2XyXV7jwuzTDHh_Dd9CM0jgDCtzAMw4n_l8f5xA3m626sdT1JtcLY8czdrIaa6u_7wmh1sDsDq8KblzZNaIQhkHi5-bJ-HCp2_NipeCkLCi4JXbeNNgpZbUOyeqlHWlkrXH2w1J0-dL0v8EHWNDbqxpPBOHpsWxZls8zatumMW5yUdmtB14ztRisIbDBsmf5qmCHxqmCV9tOGUj_q0tnp0l_LVmW45naTsLc9ysK8s_1LVgX5JE3DSUqndFzgPCxYnmOIaY5FEmY0zEn82CXne4XBVxsXoV2r9wt_4sIuHNPvhmoHwgBpNEAaH0M6ySapC5f3y0BMB-YxnHJPY7sHhp6VqTIj8coVFqbKFwenqwFFUSAtEoe-eGmOX8Rh8t1M70LjR9sDhruNVdAlDw2vzEm_tEK4Mi1yVPDCqlJxYeu3wcz4DWajZFphfa2zxisSr2hIo_E09jfwJF5YxXN4Vdy4XbkbOZL3GQB8_YySWTyze4vjfH76-tlfPPYz1kFS0-QybY8FDaPEP1munzaZzcCN6abNF8nz7rIV7lA-h2zL3PHVye3wvpLWBRcY7AvIpNBe-txGyFXfPX393Kf2pjW8CrYkXiTx_rT3MlLpziMVruIzpK5WvgG9U8yOuJ53DS5ljheNPgCMC3PB6gu4pFJWt8BxVhvH0a1QzBeP_wso7PD7JArZy3AjscWnN3j65zD5E1gk89uwmM3D-fo6FsdWLWXdSIHC3Jxh7wHr0biF9Ai-K5GIquaC9bLnnu0_YmftG3FRyL4fhLMb42iyfJhdx-6pO8X7A29E5UZTb4u0m6Hqk-5j7ripaHUbww7b6a1hOVmuVxbaa7PMh3r89LaFo3Dy4Bfed_yDVn-jjGmcuLOUTsB_2ZGvLbrIc4VaQ_g2TmdpOA7thjvszp1ZYVABg7SS2behr4bQTc2z_H25rr2Ok3GShGtvSj-Hv5QbhU3FMtwcTN3j-Obiu5qsPlZ8F_uzoT9VC-3MfGvUzR6-a9TdCMpfOuouH5lh94Ukl-iPZbasaVAA9x8QX5jidud-cpRlo5PZZ-57kb0X2iDLbXC658tPi69f7Yv-NMid2XC9_7Ry4fOJXd59NyE04QEGIKQ7gwMjr57CeZW1G67ddx9059rDQRm-sKp1Z09YaXzdokJH6L8qjvw5GqHJ81a25RaeCJ3VTpkoDAmdgG5VfwY2fFRcHgzOPXRFxUpgYmd3XlIBcrNF5S3vPyppCU-wZS9obVPItBT-m2zF8aVfxB1_EToP7vL7OJ_Hc3aH99F0TufjyXhM77b34XSSUTqbTqN5Fo2TjBbj2TQqwnE-Gc-mk_kdv6chjcOETsJpPKM0SOczVoRRmMV5Ec3plIxDrBmvAhtegVTlnYuD--l4PovvKpZipd0fqlAq8NUHifuzgdWdunchmbalJuOw4trovRTDTeX-wsXH6mQF_0IlvSuGP3oopDo6adTwys3WPn5lKu9PmrVFRjoMj4jvWlXdb41ptPsasSZ0XXKzbdMgk_3Gqd8_NUr-5vy1dhZoQtfOwn8HAAD__3ZwxCE">