Bug 61337 - Wrong indexing and runtime crash with unlimited polymorphic array.
Summary: Wrong indexing and runtime crash with unlimited polymorphic array.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: ---
Assignee: vehre
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-28 08:28 UTC by Vladimir Fuka
Modified: 2016-10-31 16:26 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-05-28 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Fuka 2014-05-28 08:28:16 UTC
module array_list

  type container
    class(*), allocatable :: items(:)
  end type


contains
    
  subroutine add_item(a, e)
    type(container),allocatable,intent(inout) :: a(:)
    class(*),intent(in) :: e(:)
    type(container),allocatable :: tmp(:)

      if (.not.allocated(a)) then
        allocate(a(1))
        allocate(a(1)%items(size(e)), source = e)
      else
        call move_alloc(a,tmp)
        allocate(a(size(tmp)+1))
        a(1:size(tmp)) = tmp
        allocate(a(size(tmp)+1)%items(size(e)), source = e)
      end if
   end subroutine
    
end module



  use array_list

  type(container), allocatable :: a_list(:)
 
  call add_item(a_list, [1, 2])

  call print(a_list(1))

contains

  subroutine print(c)
    type(container), intent(in) :: c
    
    if (allocated(c%items)) then
      select type (x=>c%items)
        type is (integer)
          print *, x
      end select
    end if
  end subroutine

end




> gfortran-4.9 alist-bug.f90 -fcheck=all -g -fbacktrace

> ./a.out 
           2           0


Expected:  1   2



With 

  call add_item(a_list, [1, 2])
  call add_item(a_list, [1, 2])

  do i = 1, size(a_list)
    call print(a_list(i))
  end do


it crashes SIGSEGVs on line:
  allocate(a(size(tmp)+1)%items(size(e)), source = e)


Tested and works on Solaris Studio 12.4.

> sunf90 alist-bug.f90 
> ./a.out 
 1 2
 1 2
Comment 1 Dominique d'Humieres 2014-05-28 17:16:15 UTC
Confirmed on 4.8 up to trunk. If the first test is compiled with -fsanitize=address, execution fails with

==63209==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000105f54d28 at pc 0x105f5433c bp 0x7fff59cb0150 sp 0x7fff59cb0148
READ of size 4 at 0x000105f54d28 thread T0
    #0 0x105f5433b (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x10000533b)
    #1 0x105f51a56 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100002a56)
    #2 0x105f544dc (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000054dc)
    #3 0x105f54883 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100005883)
    #4 0x7fff8edb75fc (/usr/lib/system/libdyld.dylib+0x35fc)

0x000105f54d28 is located 0 bytes to the right of global variable 'A.21' from 'pr61337.f90' (0x105f54d20) of size 8
0x000105f54d28 is located 56 bytes to the left of global variable 'options.23' from 'pr61337.f90' (0x105f54d60) of size 36
...

The modified case (call add_item twice) fails with

==63217==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0001084c0ce8 at pc 0x1084c0112 bp 0x7fff57744130 sp 0x7fff57744128
READ of size 4 at 0x0001084c0ce8 thread T0
    #0 0x1084c0111 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100005111)
    #1 0x1084bd82c (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x10000282c)
    #2 0x1084c02b4 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000052b4)
    #3 0x1084c07c3 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000057c3)
    #4 0x7fff8edb75fc (/usr/lib/system/libdyld.dylib+0x35fc)

0x0001084c0ce8 is located 0 bytes to the right of global variable 'A.21' from 'pr61337_1.f90' (0x1084c0ce0) of size 8
0x0001084c0ce8 is located 56 bytes to the left of global variable 'A.24' from 'pr61337_1.f90' (0x1084c0d20) of size 8
Comment 2 Vladimir Fuka 2015-09-02 10:13:44 UTC
The first is fixed on trunk apparently by https://gcc.gnu.org/ml/fortran/2015-07/msg00038.html


The modification

  call add_item(a_list, [1, 2])
  call add_item(a_list, [1, 2])

  do i = 1, size(a_list)
    call print(a_list(i))
  end do


still causes a segfault.
Comment 3 Vladimir Fuka 2015-09-02 13:55:58 UTC
The crash is at line 22:

allocate(a(size(tmp)+1)%items(size(e)), source = e)

ASAN:SIGSEGV
=================================================================
==5902==ERROR: AddressSanitizer: SEGV on unknown address 0x60c0c08ef6b0 (pc 0x0000004086ed bp 0x7ffec4dcc6b0 sp 0x7ffec4dcc490 T0)
    #0 0x4086ec in __array_list_MOD_add_item /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:22
    #1 0x408ff4 in MAIN__ /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:35
    #2 0x4096d5 in main /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:30
    #3 0x7f898a67eb04 in __libc_start_main (/lib64/libc.so.6+0x21b04)
    #4 0x400e38  (/home/vf1r14/f/testy/stackoverflow/a.out+0x400e38)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:22 __array_list_MOD_add_item
==5902==ABORTING
Comment 4 graham.stott 2015-09-02 14:09:21 UTC
<div>-------- Original message --------</div><div>From: "vladimir.fuka at gmail dot com" <gcc-bugzilla@gcc.gnu.org> </div><div>Date:02/09/2015  14:55  (GMT+00:00) </div><div>To: gcc-bugs@gcc.gnu.org </div><div>Subject: [Bug fortran/61337] Wrong indexing and runtime crash with unlimited polymorphic array. </div><div>
</div>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61337

--- Comment #3 from Vladimir Fuka <vladimir.fuka at gmail dot com> ---
The crash is at line 22:

allocate(a(size(tmp)+1)%items(size(e)), source = e)

ASAN:SIGSEGV
=================================================================
==5902==ERROR: AddressSanitizer: SEGV on unknown address 0x60c0c08ef6b0 (pc
0x0000004086ed bp 0x7ffec4dcc6b0 sp 0x7ffec4dcc490 T0)
    #0 0x4086ec in __array_list_MOD_add_item
/home/vf1r14/f/testy/stackoverflow/pr61337b.f90:22
    #1 0x408ff4 in MAIN__ /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:35
    #2 0x4096d5 in main /home/vf1r14/f/testy/stackoverflow/pr61337b.f90:30
    #3 0x7f898a67eb04 in __libc_start_main (/lib64/libc.so.6+0x21b04)
    #4 0x400e38  (/home/vf1r14/f/testy/stackoverflow/a.out+0x400e38)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/home/vf1r14/f/testy/stackoverflow/pr61337b.f90:22 __array_list_MOD_add_item
==5902==ABORTING
Comment 5 vehre 2016-10-22 12:34:11 UTC
Author: vehre
Date: Sat Oct 22 12:33:38 2016
New Revision: 241439

URL: https://gcc.gnu.org/viewcvs?rev=241439&root=gcc&view=rev
Log:
gcc/fortran/ChangeLog:

2016-10-22  Andre Vehreschild  <vehre@gcc.gnu.org>

	PR fortran/43366
	PR fortran/51864
	PR fortran/57117
	PR fortran/61337
	PR fortran/61376
	* primary.c (gfc_expr_attr): For transformational functions on classes
	get the attrs from the class argument.
	* resolve.c (resolve_ordinary_assign): Remove error message due to
	feature implementation.  Rewrite POINTER_ASSIGNS to ordinary ones when
	the right-hand side is scalar class object (with some restrictions).
	* trans-array.c (trans_array_constructor): Create the temporary from
	class' inner type, i.e., the derived type.
	(build_class_array_ref): Add support for class array's storage of the
	class object or the array descriptor in the decl saved descriptor.
	(gfc_conv_expr_descriptor): When creating temporaries for class objects
	add the class object's handle into the decl saved descriptor.
	(structure_alloc_comps): Use the common way to get the _data component.
	(gfc_is_reallocatable_lhs): Add notion of allocatable class objects.
	* trans-expr.c (gfc_find_and_cut_at_last_class_ref): Remove the only ref
	only when the expression's type is BT_CLASS.
	(gfc_trans_class_init_assign): Correctly handle class arrays.
	(gfc_trans_class_assign): Joined into gfc_trans_assignment_1.
	(gfc_conv_procedure_call): Support for class types as arguments.
	(trans_get_upoly_len): For unlimited polymorphics retrieve the _len
	component's tree.
	(trans_class_vptr_len_assignment): Catch all ways to assign the _vptr
	and _len components of a class object correctly.
	(pointer_assignment_is_proc_pointer): Identify assignments of
	procedure pointers.
	(gfc_trans_pointer_assignment): Enhance support for class object pointer
	assignments.
	(gfc_trans_scalar_assign): Removed assert.
	(trans_class_assignment): Assign to a class object.
	(gfc_trans_assignment_1): Treat class objects correctly.
	(gfc_trans_assignment): Propagate flags to trans_assignment_1.
	* trans-stmt.c (gfc_trans_allocate): Use gfc_trans_assignment now
	instead of copy_class_to_class.
	* trans-stmt.h: Function prototype removed.
	* trans.c (trans_code): Less special casing for class objects.
	* trans.h: Added flags to gfc_trans_assignment () prototype.

gcc/testsuite/ChangeLog:

2016-10-22  Andre Vehreschild  <vehre@gcc.gnu.org>

        Forgot to add on original commit.
        * gfortran.dg/coarray_alloc_comp_2.f08: New test.

2016-10-22  Andre Vehreschild  <vehre@gcc.gnu.org>

	PR fortran/43366
	PR fortran/57117
	PR fortran/61337
	* gfortran.dg/alloc_comp_class_5.f03: New test.
	* gfortran.dg/class_allocate_21.f90: New test.
	* gfortran.dg/class_allocate_22.f90: New test.
	* gfortran.dg/realloc_on_assign_27.f08: New test.



Added:
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_class_5.f03
    trunk/gcc/testsuite/gfortran.dg/class_allocate_21.f90
    trunk/gcc/testsuite/gfortran.dg/class_allocate_22.f90
    trunk/gcc/testsuite/gfortran.dg/coarray_alloc_comp_2.f08
    trunk/gcc/testsuite/gfortran.dg/realloc_on_assign_27.f08
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/primary.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/fortran/trans-stmt.h
    trunk/gcc/fortran/trans.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
Comment 6 vehre 2016-10-24 17:00:29 UTC
Waiting one week for regression reports.
Comment 7 vehre 2016-10-31 16:26:34 UTC
No complaints so far, closing.