Bug 61775 - Allocatable array initialized by implied-do loop array constructor gives invalid memory reference
Summary: Allocatable array initialized by implied-do loop array constructor gives inva...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.9.0
: P4 normal
Target Milestone: 8.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-10 17:02 UTC by Robert Rosenberg
Modified: 2018-03-14 00:50 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-07-10 00:00:00


Attachments
initializes allocatable array with implied-do loop array constructor (445 bytes, text/plain)
2014-07-10 17:02 UTC, Robert Rosenberg
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Rosenberg 2014-07-10 17:02:11 UTC
Created attachment 33104 [details]
initializes allocatable array with implied-do loop array constructor

Received an 'invalid memory reference' run time error from gfortran code that initializes an allocatable array with an implied-do loop array constructor.  Runs fine for Intel and Cray compilers, but fails for both GNU and PGI compilers.

        program pi
        real   , allocatable :: x(:)
        integer              :: n
        n  = 10000
        x = [ (i,i=1,n) ]
        print*,x(n)
        end
Comment 1 kargls 2014-07-10 20:29:39 UTC
Whatever the issue was, it appears to be fixed in HEAD.

troutmask:sgk[205] gfc4x -o z h.f90
troutmask:sgk[206] ./z
   10000.0000
troutmask:sgk[207] gfc49 -o z h.f90
troutmask:sgk[208] ./z

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Comment 2 kargls 2014-07-10 20:34:23 UTC
(In reply to kargl from comment #1)
> Whatever the issue was, it appears to be fixed in HEAD.
> 
> troutmask:sgk[205] gfc4x -o z h.f90
> troutmask:sgk[206] ./z
>    10000.0000
> troutmask:sgk[207] gfc49 -o z h.f90
> troutmask:sgk[208] ./z
> 
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.

I take it back.  It is broken with optimizations.

troutmask:sgk[213] gfc4x -o z -O -fcheck=all h.f90 && ./z
At line 6 of file h.f90
Fortran runtime error: Index '10000' of dimension 1 of array 'x' above upper bound of 1
Segmentation fault (core dumped)
Comment 3 Dominique d'Humieres 2014-07-10 20:36:53 UTC
> Whatever the issue was, it appears to be fixed in HEAD.

I don't think so. Could you run the test with -fsanitize=address. On x86_64-apple-darwin13 r212433, I get at run time:

=================================================================
==4401==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000e014 at pc 0x1064f08c1 bp 0x7fff597100e0 sp 0x7fff597100d8
WRITE of size 4 at 0x60200000e014 thread T0
    #0 0x1064f08c0 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x1000018c0)
    #1 0x1064f0d19 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001d19)
    #2 0x7fff922ef5fc (/usr/lib/system/libdyld.dylib+0x35fc)

0x60200000e014 is located 0 bytes to the right of 4-byte region [0x60200000e010,0x60200000e014)
allocated by thread T0 here:
    #0 0x10652a4c9 (/opt/gcc/gcc4.10p-212433/lib/libasan.1.dylib+0x314c9)
    #1 0x1064f0846 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001846)
    #2 0x1064f0d19 (/Users/dominiq/Documents/Fortran/g95bench/win/f90/bug/a.out+0x100001d19)
    #3 0x7fff922ef5fc (/usr/lib/system/libdyld.dylib+0x35fc)

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 ??
Shadow bytes around the buggy address:
  0x1c0400001bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x1c0400001c00: fa fa[04]fa fa fa 06 fa fa fa 06 fa fa fa 05 fa
  0x1c0400001c10: fa fa 00 fa fa fa 00 00 fa fa 03 fa fa fa 00 02
  0x1c0400001c20: fa fa 00 07 fa fa 00 fa fa fa 00 00 fa fa 00 00
  0x1c0400001c30: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x1c0400001c40: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x1c0400001c50: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  ASan internal:           fe
==4401==ABORTING
Comment 4 Mikael Morin 2014-07-11 20:38:04 UTC
This seems to fix it here (not heavily tested):


Index: trans-expr.c
===================================================================
--- trans-expr.c	(révision 209169)
+++ trans-expr.c	(copie de travail)
@@ -7932,9 +7932,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr
 
   /* Walk the lhs.  */
   lss = gfc_walk_expr (expr1);
-  if (gfc_is_reallocatable_lhs (expr1)
-	&& !(expr2->expr_type == EXPR_FUNCTION
-	     && expr2->value.function.isym != NULL))
+  if (gfc_is_reallocatable_lhs (expr1))
     lss->is_alloc_lhs = 1;
   rss = NULL;
   if (lss != gfc_ss_terminator)
Comment 5 Dominique d'Humieres 2014-07-12 11:44:21 UTC
(In reply to comment #4)
> This seems to fix it here (not heavily tested): ...

Confirmed, regtested without regression and no obvious problem with my other tests.
Comment 6 lkrupp 2016-09-18 07:16:37 UTC
I started looking at this until I read all of the comments and realized that someone had already come up with a patch, and one that is probably better and certainly simpler than whatever I would have done.

It might be worth noting that the problem seems to come up when an array is passed to an intrinsic function that returns a scalar when its argument is a scalar and that returns an array when it's passed an array.  In the sample program in the description, the intrinsic function is integer to real conversion.  The following sample program reproduces that problem with a simple array instead of an implied do loop, and also with the square root function.  Compiling this with -fbounds-check makes the program fail on the assignment statement:

program assign_allocatable
implicit none

  call s_int_real_cvt
  call s_sqrt

contains

  subroutine s_int_real_cvt
  implicit none
  integer, parameter :: r(3) = [101, 102, 103]
  real, allocatable :: k(:)

  k = r

  if (any(k /= r)) call abort

  return
  end subroutine

  subroutine s_sqrt
  implicit none
  real, parameter :: r(5) = [1, 4, 9, 16, 25]
  real, allocatable :: a(:)

  a = sqrt(r)

  if (any(a /= [1, 2, 3, 4, 5])) call abort

  return
  end subroutine

end program

Array-value intrinsics like TRANSFER and PACK don't seem to trigger this problem.
Comment 7 kargls 2018-03-13 18:33:37 UTC
I think that this is now fixed on trunk.  Don't know which patch.

% gfcx -o z a.f90 && ./z
   10000.0000    
% gfcx -o z a.f90 -O2 -fcheck=all && ./z
   10000.0000    
% valgrind ./z
==85120== Memcheck, a memory error detector
==85120== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==85120== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==85120== Command: ./z
==85120== 
   10000.0000    
==85120== 
==85120== HEAP SUMMARY:
==85120==     in use at exit: 0 bytes in 0 blocks
==85120==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==85120== 
==85120== All heap blocks were freed -- no leaks are possible
==85120== 
==85120== For counts of detected and suppressed errors, rerun with: -v
==85120== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I've read the tree dump for -fdump-tree-optimized and it appears to
do the right think with expanding the constructor, allocating, and
freeing memory.

Both 6-branch and 7-branch still fail
% gfc6 -o z a.f90 -O2 -fcheck=all && ./z
 Segmentation fault (core dumped)
% gfc7 -o z a.f90 -O2 -fcheck=all && ./z
Segmentation fault (core dumped)

I would like to close this as fixed after committing the following
testcase

        program pi
        real   , allocatable :: x(:)
        integer              :: n
        n  = 10000
        x = [ (i,i=1,n) ]
        if (x(n) /= 10000) stop 1
        end
Comment 8 Thomas Koenig 2018-03-13 19:05:54 UTC
(In reply to kargl from comment #7)

> I would like to close this as fixed after committing the following
> testcase
> 
>         program pi
>         real   , allocatable :: x(:)
>         integer              :: n
>         n  = 10000
>         x = [ (i,i=1,n) ]
>         if (x(n) /= 10000) stop 1
>         end

Sure, go ahead.
Comment 9 kargls 2018-03-14 00:46:18 UTC
Author: kargl
Date: Wed Mar 14 00:45:45 2018
New Revision: 258509

URL: https://gcc.gnu.org/viewcvs?rev=258509&root=gcc&view=rev
Log:
2018-03-13  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/61775
	* gfortran.dg/pr61775.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/pr61775.f90
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 10 kargls 2018-03-14 00:50:37 UTC
Closing as fixed on trunk.  I've converted the
code in comment #7 to a testcase, and committed
it so hopefully it won't get unfixed.