------- 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