Skip to content

C to Fortran string conversion includes a null terminator in some cases #13375

@benmenadue

Description

@benmenadue

This is with v5.0.8, but the code looks the same as in main.

At the moment, ompi_fortran_string_c2f uses opal_string_copy to copy a string into the destination and then replaces the null-terminator and all remaining characters of the buffer with spaces as expected by the Fortran standard.

/*
* Copy a C string into a Fortran string. Note that when Fortran
* copies strings, even if it operates on subsets of the strings, it
* is expected to zero out the rest of the string with spaces. Hence,
* when calling this function, the "len" parameter should be the
* compiler-passed length of the entire string, even if you're copying
* over less than the full string. Specifically:
*
* http://www.ibiblio.org/pub/languages/fortran/ch2-13.html
*
* "Whole operations 'using' only 'part' of it, e.g. assignment of a
* shorter string, or reading a shorter record, automatically pads the
* rest of the string with blanks."
*/
int ompi_fortran_string_c2f(const char *cstr, char *fstr, int len)
{
int i;
opal_string_copy(fstr, cstr, len);
for (i = strlen(cstr); i < len; ++i) {
fstr[i] = ' ';
}
return OMPI_SUCCESS;
}

However, this fails when the length of the destination is less than or equal to the length of the source string: opal_string_copy copies up to the length of the destination but then replaces the last character with \0. Then the loop to replace the rest of the destination with spaces doesn't do anything (because it starts from the length of the source) and you're left with a \0 as the last character in the destination.

I noticed this because it breaks mpifh's and use_mpi's MPI_Info_get when the destination is exactly the length of the value:

use mpi
character(len=3) :: value = "bar"
integer :: info, ierr
logical :: flag
call MPI_Info_create(info, ierr)
call MPI_Info_set(info, "foo", value, ierr)
call MPI_Info_get(info, "foo", len(value), value, flag, ierr)
call MPI_Info_free(info, ierr)

results in value containing ba\0 when it should still contain bar.

As an aside: MPI_Info_get / ompi_info_get_f doesn't actually use the valuelen argument and instead only uses the compiler-provided length argument. I'm not sure what the behaviour should be when given a smaller length than the actual destination, especially if the value is larger than the provided length. At the moment it will return the whole value (up to (length-1) of the destination) but should it instead be truncating it there and filling the rest of the destination with spaces?

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions