------- Comment #18 from mikael at gcc dot gnu dot org  2008-11-17 19:43 -------
The problem is in ByteToString. 
The assignment of the transfer result is changed to a memmove. 
The memmove is controlled by the size of both the lhs and the rhs. 
The size of the rhs (actually the charlen=3 in this case) is not the same as
that of the actual data, as the charlen was copied from string's typespec in
transfer. 
Thus, we are copying 3 bytes, instead of 2. 

I think the code is still a valid program and a wrong-code, as while the
standard allow to have a result (partially) undefined/processor-dependent, it
doesn't allow to read unallocated memory. 


module TransferBug
  type ByteType
    integer(kind=1) :: singleByte
  end type
  type(ByteType) :: BytesPrototype(2)
contains
  function StringToBytes(v) result (bytes)
    character(len=2) :: v
    type (ByteType) :: bytes(2)!size(transfer(v, BytesPrototype)))
    bytes = transfer('Hi', BytesPrototype)
  end function

  subroutine BytesToString(bytes, string)
    type (ByteType) :: bytes(2)
    character(len=*) :: string
    string = transfer(bytes, string)
  end subroutine
end module

program main
  use TransferBug
  character(len=3) :: str
  type(ByteType) :: i(1)
  call BytesToString( StringToBytes('Hi'), str )
end program



Valgrind doesn't complain on this testcase, but I strongly suspect that the bug
is still there. Using the commented array size forces the creation of
temporaries, and then valgrind catches the error. 


Now, how to fix this?
We could unconditionally create a temporary in transfer, so that we have both
the original data size and the target data size at the time of the memmove. 
That would probably mean a lot of regressions, and not only speed ones. 
We could keep track of the original data size.
I must admit I'm not satisfied with this one either. 
What else?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34955

Reply via email to