[Bug fortran/93762] Truncation of deferred-length string when passing as optional

kargl at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Apr 10 22:36:24 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93762

kargl at gcc dot gnu.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kargl at gcc dot gnu.org

--- Comment #2 from kargl at gcc dot gnu.org ---
(In reply to Thomas Koenig from comment #1)
> Unfortunately, the test case fails with different ways on
> current trunk:
> 
> $ gfortran -g  a.f90
> $ ./a.out
>  at bot of deepest_call, str is "12345"
> 
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.
> 
> Backtrace for this error:
> #0  0x7f0a66c3059f in ???
>         at
> /usr/src/debug/glibc-2.26-lp151.19.11.1.x86_64/signal/../sysdeps/unix/sysv/
> linux/x86_64/sigaction.c:0
> #1  0x400c65 in __interface_call_m_MOD_interface_call
>         at /tmp/a.f90:20
> #2  0x400d99 in MAIN__
>         at /tmp/a.f90:32
> #3  0x400f0b in main
>         at /tmp/a.f90:25
> Speicherzugriffsfehler (Speicherabzug geschrieben)
> 
> (gdb) r a.f90 
> Starting program: /tmp/a.out a.f90
>  at bot of deepest_call, str is "12345"
> 
> Program received signal SIGSEGV, Segmentation fault.
> _gfortran_string_len_trim (s=0x6068d0 "12345", len=<optimized out>) at
> ../../../gcc/libgfortran/intrinsics/string_intrinsics_inc.c:231
> 231               if (*((unsigned long*) (s + i + 1)) != blank_longword)
> (gdb) p s
> $1 = 0x6068d0 "12345"
> (gdb) p i
> $2 = 564082115390472183
> 
> Seems like uninitialzed memory for i.
> 
> Valgrind confirms this:
> 
> $ valgrind ./a.out
> ==5621== Memcheck, a memory error detector
> ==5621== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
> ==5621== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
> ==5621== Command: ./a.out
> ==5621== 
>  at bot of deepest_call, str is "12345"
> ==5621== Conditional jump or move depends on uninitialised value(s)
> ==5621==    at 0x50A29A5: _gfortran_string_len_trim
> (string_intrinsics_inc.c:188)
> ==5621==    by 0x50A2A87: _gfortran_string_trim (string_intrinsics_inc.c:168)
> ==5621==    by 0x400C65: __interface_call_m_MOD_interface_call (a.f90:20)
> ==5621==    by 0x400D99: MAIN__ (a.f90:32)
> ==5621==    by 0x400F0B: main (a.f90:25)
> 
> Not sure if this ever worked in a released version.

I doubt it ever worked.  It seems that the length is not getting
set properly for the returning string.  Should this be propagated
up the call change in the hidden string length argument.  Here's a
modified testcase where I print out lengths of str.

module deepest_call_m
   implicit none
   contains
      subroutine deepest_call(str)
         character(len=:), allocatable, optional :: str
         character(len=5) t
         t = '12345'
         if (present(str)) then
            str = t
            write(*,*) 'at bot of deepest_call, str is "'//trim(str)//'"'
         end if
         print *, 'len = ', len(str)
         print '(A)', 'Returning from deepest_call'
      end subroutine deepest_call
end module deepest_call_m

module interface_call_m
   implicit none
   contains
      subroutine interface_call(str)
         use deepest_call_m, only : deepest_call
         character(len=:), allocatable, optional :: str
         if (present(str)) then
            call deepest_call(str)
            print *, 'len = ', len(str)
            write(*,*) 'at bot of interface_call, str is "'//trim(str)//'"'
         end if
      end subroutine interface_call
end module interface_call_m

program main
   use interface_call_m, only : interface_call
   implicit none
   character(len=:), allocatable :: str
   call interface_call(str)
   write(*,*) 'at bot of main, str is "'//trim(str)//'"'
end program main

I get

% gfcx -o z -g a.f90 && ./z
 at bot of deepest_call, str is "12345"
 len =            5
Returning from deepest_call
 len =    134516966
Segmentation fault (core dumped)

len = 5 is in deepest_call and the correct value.
len = 134516966 seems to be a bit too large.


More information about the Gcc-bugs mailing list