Bug 80945 - Invalid code with allocatable character array in READ/WRITE statement
Summary: Invalid code with allocatable character array in READ/WRITE statement
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: wrong-code
Depends on:
Blocks: 68241 35339
  Show dependency treegraph
 
Reported: 2017-06-01 18:01 UTC by Nicolas Koenig
Modified: 2018-03-03 13:18 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-06-01 00:00:00


Attachments
Test Case (208 bytes, text/plain)
2017-06-01 18:01 UTC, Nicolas Koenig
Details
A demo patch for the PR (383 bytes, patch)
2018-02-15 23:15 UTC, Paul Thomas
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolas Koenig 2017-06-01 18:01:05 UTC
Created attachment 41446 [details]
Test Case

Trying to compile the testcase with "-O" produces invalid code, while compiling it without leads to a segfault.

gcc@dcm-linux:~/pr/35339> gfortran -O z5.f90                                                                                                                                                                                                                                  
gcc@dcm-linux:~/pr/35339> ./a.out                                                                                                                                                                                                                                    
 c      foo       bar       xyzzy                                                                                                                                                                                                                                              
 ca     xyzzy                                                                                                                                                                                                                                                                  
gcc@dcm-linux:~/pr/35339> gfortran z5.f90                                                                                                                                                                                                                                   
gcc@dcm-linux:~/pr/35339> ./a.out                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                               
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.                                                                                                                                                                                                
                                                                                                                                                                                                                                                                               
Backtrace for this error:                                                                                                                                                                                                                                                      
#0  0x7f37dee45adf in ???                                                                                                                                                                                                                                                      
#1  0x7f37dee97d15 in ???                                                                                                                                                                                                                                                      
#2  0x7f37dfb03a50 in read_default_char1                                                                                                                                                                                                                                       
        at ../../../trunk/libgfortran/io/read.c:429                                                                                                                                                                                                                            
#3  0x7f37dfb0809c in formatted_transfer_scalar_read                                                                                                                                                                                                                           
        at ../../../trunk/libgfortran/io/transfer.c:1591                                                                                                                                                                                                                       
#4  0x7f37dfb08f2c in formatted_transfer                                                                                                                                                                                                                                       
        at ../../../trunk/libgfortran/io/transfer.c:2270                                                                                                                                                                                                                       
#5  0x400cb3 in ???                                                                                                                                                                                                                                                            
#6  0x400e43 in ???                                                                                                                                                                                                                                                            
#7  0x7f37dee31469 in ???                                                                                                                                                                                                                                                      
#8  0x400909 in ???                                                                                                                                                                                                                                                            
        at ../sysdeps/x86_64/start.S:120                                                                                                                                                                                                                                       
#9  0xffffffffffffffff in ???
Segmentation fault (core dumped)
Comment 1 Thomas Koenig 2017-06-01 19:25:10 UTC
1. write also fails (no surprise there)
2. ca is OK, ca(1:3) is not.

$ cat u.f90
program main
    implicit none
    integer:: i
    integer, parameter:: N = 10
    character(len=:), dimension(:),allocatable:: ca
    character(len=50):: buffer
    allocate(character(len=N):: ca(3))
    buffer = "foo  bar  xyzzy"
    ca(1) = "foo"
    ca(2) = "bar"
    ca(3) = "xyzzy"
    write (*, '(3A5)') ca
    write (*, '(3A5)') ca(1:3)
end program

$ gfortran u.f90 && ./a.out
foo  bar  xyzzy

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7f38e528406f in ???
#1  0x7f38e5384440 in ???
#2  0x7f38e5eeb67c in formatted_transfer_scalar_write
        at ../../../gcc-7/libgfortran/io/transfer.c:2059
#3  0x7f38e5eeb81c in formatted_transfer
        at ../../../gcc-7/libgfortran/io/transfer.c:2279
#4  0x400d03 in ???
#5  0x400d55 in ???
#6  0x7f38e526f540 in ???
#7  0x400839 in ???
        at ../sysdeps/x86_64/start.S:120
#8  0xffffffffffffffff in ???
Speicherzugriffsfehler (Speicherabzug geschrieben)
Comment 2 Thomas Koenig 2017-06-01 19:52:07 UTC
The dtype is messed up.  Breaking at _gfortran_transfer_array
for the test case in cmment #1 shows

Breakpoint 1, _gfortran_transfer_array (dtp=0x7fffffffd910, desc=0x7fffffffdaf0, kind=1, charlen=10) at ../../../gcc-7/libgfortran/io/transfer.c:2409
2409      if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
(gdb) p *desc
$3 = {base_addr = 0x605ff0 "foo       bar       xyzzy     ", offset = 18446744073709551615, dtype = 689, dim = {{_stride = 1, lower_bound = 1, _ubound = 3}, {_stride = 8241976683187367782, 
      lower_bound = 2340036147838197792, _ubound = 2314885530818453536}, {_stride = 2314885530818453536, lower_bound = 2314885530818453536, _ubound = 2314885530818453536}, {_stride = 8224, 
      lower_bound = 44024187392, _ubound = 140737488346016}, {_stride = 0, lower_bound = 4196368, _ubound = 140737488346240}, {_stride = 140737488346016, lower_bound = 4197718, 
      _ubound = 140737488346248}, {_stride = 4294967296, lower_bound = 4197728, _ubound = 140737336403265}}}
(gdb) c
Continuing.
foo  bar  xyzzy

Breakpoint 1, _gfortran_transfer_array (dtp=0x7fffffffd910, desc=0x7fffffffd8e0, kind=1, charlen=10) at ../../../gcc-7/libgfortran/io/transfer.c:2409
2409      if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
(gdb) p *desc
$4 = {base_addr = 0x605ff0 "foo       bar       xyzzy     ", offset = 0, dtype = -60931979599, dim = {{_stride = 1, lower_bound = 1, _ubound = 3}, {_stride = 25769807872, lower_bound = 4198108, 
      _ubound = 13}, {_stride = 0, lower_bound = 0, _ubound = 0}, {_stride = 0, lower_bound = 0, _ubound = 0}, {_stride = 4198114, lower_bound = 5, _ubound = 0}, {_stride = 0, lower_bound = 0, 
      _ubound = 0}, {_stride = 0, lower_bound = 0, _ubound = 0}}}
Comment 3 Thomas Koenig 2017-06-01 20:45:04 UTC
Really strange - the tree dumps look OK at first glance.

  D.3543 = (sizetype) NON_LVALUE_EXPR <.ca>;

and later on

        parm.3.dtype = ((integer(kind=8)) SAVE_EXPR <D.3543> << 6) + 49;
        parm.3.dim[0].lbound = 1;
        parm.3.dim[0].ubound = 3;
        parm.3.dim[0].stride = 1;
        parm.3.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict) ca.data)[1 - ca.dim[0].lbound];
        parm.3.offset = 0;
        _gfortran_transfer_array_write (&dt_parm.2, &parm.3, 1, .ca);

What am I missing?
Comment 4 Jerry DeLisle 2017-06-02 21:56:31 UTC
(In reply to Thomas Koenig from comment #3)
> Really strange - the tree dumps look OK at first glance.
> 

Maybe missing something in a backend declaration?
Comment 5 Dominique d'Humieres 2017-06-03 14:16:05 UTC
The code is correctly compiled if I replace

    character(len=:), dimension(:),allocatable:: ca

with

    character(len=N), dimension(:),allocatable:: ca

or

    read (buffer, '(3A5)') ca(1:3)

with

    read (buffer, '(3A5)') ca

It could be related to pr68241.
Comment 6 Thomas Koenig 2017-06-05 12:47:20 UTC
If this patch is fixed, please remember to remove the extra
check in frontend-passes.c (traverse_io_block). Just grep
for 80945.
Comment 7 Thomas Koenig 2018-02-13 21:18:11 UTC
Still fails with current trunk.

Code from comment#1, somewhat simplified:

program main
    implicit none
    integer:: i
    integer, parameter:: N = 10
    character(len=:), dimension(:),allocatable:: ca
    allocate(character(len=N):: ca(3))
    ca(1) = "foo"
    ca(2) = "bar"
    ca(3) = "xyzzy"
    write (*, '(3A5)') ca(1:3)
end program

This yields on gcc110:

foo  foo  foo  

Looking at the tree dump, we see

MAIN__ ()
{
  integer(kind=8) .ca;
  struct array01_unknown ca;
  bitsizetype D.2078;
  sizetype D.2079;

  D.2078 = (bitsizetype) (sizetype) NON_LVALUE_EXPR <.ca> * 8;
  D.2079 = (sizetype) NON_LVALUE_EXPR <.ca>;

and later

  {
    integer(kind=4) overflow.0;

    .ca = 10;
    ca.dtype = {.elem_len=(unsigned long) SAVE_EXPR <(sizetype) NON_LVALUE_EXPR <.ca>>, .rank=1, .type=6};

...

    _gfortran_st_write (&dt_parm.1);
      {
        struct array01_unknown parm.2;

        parm.2.dtype = {.elem_len=(unsigned long) SAVE_EXPR <D.2079>, .rank=1, .type=6};
        parm.2.dim[0].lbound = 1;
        parm.2.dim[0].ubound = 3;
        parm.2.dim[0].stride = 1;
        parm.2.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict) ca.data)[1 - ca.dim[0].lbound];
        parm.2.offset = ca.offset;
        _gfortran_transfer_array_write (&dt_parm.1, &parm.2, 1, .ca);

so the dtype gets its elem_len from the uninitialized copy of .ca
instead of the correctly initialized value later.

Paul, does this ring any bells?
Comment 8 paul.richard.thomas@gmail.com 2018-02-14 14:26:59 UTC
Hi Thomas,

It doesn't just ring bells, it lets off sirens and sets the marching
bands to marching!

I can only find rather old sources on the web but I seem to remember
that the new dtype generation uses gfc_get_element_type , which makes
use of GFC_TYPE_ARRAY_DATAPTR_TYPE. If this latter does not get reset
with each reallocation it would be the source of the trouble.

I'll try to take a look tonight, although the 14th February might prevail :-)

Paul

On 13 February 2018 at 21:18, tkoenig at gcc dot gnu.org
<gcc-bugzilla@gcc.gnu.org> wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80945
>
> --- Comment #7 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
> Still fails with current trunk.
>
> Code from comment#1, somewhat simplified:
>
> program main
>     implicit none
>     integer:: i
>     integer, parameter:: N = 10
>     character(len=:), dimension(:),allocatable:: ca
>     allocate(character(len=N):: ca(3))
>     ca(1) = "foo"
>     ca(2) = "bar"
>     ca(3) = "xyzzy"
>     write (*, '(3A5)') ca(1:3)
> end program
>
> This yields on gcc110:
>
> foo  foo  foo
>
> Looking at the tree dump, we see
>
> MAIN__ ()
> {
>   integer(kind=8) .ca;
>   struct array01_unknown ca;
>   bitsizetype D.2078;
>   sizetype D.2079;
>
>   D.2078 = (bitsizetype) (sizetype) NON_LVALUE_EXPR <.ca> * 8;
>   D.2079 = (sizetype) NON_LVALUE_EXPR <.ca>;
>
> and later
>
>   {
>     integer(kind=4) overflow.0;
>
>     .ca = 10;
>     ca.dtype = {.elem_len=(unsigned long) SAVE_EXPR <(sizetype) NON_LVALUE_EXPR
> <.ca>>, .rank=1, .type=6};
>
> ...
>
>     _gfortran_st_write (&dt_parm.1);
>       {
>         struct array01_unknown parm.2;
>
>         parm.2.dtype = {.elem_len=(unsigned long) SAVE_EXPR <D.2079>, .rank=1,
> .type=6};
>         parm.2.dim[0].lbound = 1;
>         parm.2.dim[0].ubound = 3;
>         parm.2.dim[0].stride = 1;
>         parm.2.data = (void *) &(*(character(kind=1)[0:][1:.ca] * restrict)
> ca.data)[1 - ca.dim[0].lbound];
>         parm.2.offset = ca.offset;
>         _gfortran_transfer_array_write (&dt_parm.1, &parm.2, 1, .ca);
>
> so the dtype gets its elem_len from the uninitialized copy of .ca
> instead of the correctly initialized value later.
>
> Paul, does this ring any bells?
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.
Comment 9 Paul Thomas 2018-02-15 23:15:47 UTC
Created attachment 43438 [details]
A demo patch for the PR

This does the job but sucks stylistically. I will sort out something better.

It does regtest fine, though :-) It also fixes:

program main
    implicit none
    integer:: i
    integer, parameter:: N = 10
    character(len=:), dimension(:),allocatable:: ca
    character(len=:), dimension(:,:),allocatable:: cb
    allocate(character(len=N) :: ca(3))
    ca(1) = "foo"
    ca(2) = "bar"
    ca(3) = "xyzzy"
    write (*, '(3A5)') ca(1:3)
    allocate(character(len=N) :: cb(3,2))
    cb(1,1) = "foo"
    cb(2,1) = "bar"
    cb(3,1) = "xyzzy"
    write (*, '(3A5)') cb(1:3,1) ! Hence the assignment of the rank!          
end program

Paul
Comment 10 Paul Thomas 2018-02-18 08:59:38 UTC
Author: pault
Date: Sun Feb 18 08:59:06 2018
New Revision: 257788

URL: https://gcc.gnu.org/viewcvs?rev=257788&root=gcc&view=rev
Log:
2018-02-18  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/80945
	* trans-array.c (gfc_conv_expr_descriptor): Set parmtype from
	the typenode in the case of deferred length characters.

2018-02-18  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/80945
	* gfortran.dg/associate_35.f90: Remove error, add stop n's and
	change to run.


Added:
    trunk/gcc/testsuite/gfortran.dg/deferred_character_19.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/testsuite/ChangeLog
Comment 11 Thomas Koenig 2018-02-19 18:22:17 UTC
Author: tkoenig
Date: Mon Feb 19 18:21:45 2018
New Revision: 257814

URL: https://gcc.gnu.org/viewcvs?rev=257814&root=gcc&view=rev
Log:
2018-02-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/35339
	* frontend-passes.c (traverse_io_block): Remove workaround for
	PR 80945.

2018-02-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/35339
	* gfortran.dg/implied_do_io_4.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/implied_do_io_4.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/frontend-passes.c
    trunk/gcc/testsuite/ChangeLog
Comment 12 Dominique d'Humieres 2018-02-21 11:54:45 UTC
Fixed?
Comment 13 Paul Thomas 2018-03-03 13:18:32 UTC
Fixed on trunk.

Thanks for the report.

Paul and Thomas