Dear Marcello, On 26 March 2018 at 17:32, Marcello Seri <[email protected]> wrote: > In `ocaml-opasswd` (https://github.com/xapi-project/ocaml-opasswd) we are > using ctypes to bind some functions from `passwd.h` and `shadow.h`. In rare > cases, when using the library to update an entry in the shadow file, it > seems that the two strings in the passwd struct are read from uninitialised > memory instead of being copies of the ocaml strings that we passed to create > the new shadow struct. > > The code is here: > https://github.com/xapi-project/ocaml-opasswd/blob/master/lib/shadow.ml#L20 > and my fear is that declaring those as `string`: > ``` > let sp_name = field shadow_t "sp_name" string > let sp_passwd = field shadow_t "sp_passwd" string > ``` > and then reading or writing them with > ``` > name = getf !@sp sp_name; > passwd = getf !@sp sp_passwd; > ``` > and > ``` > setf sp_t sp_name sp.name; > setf sp_t sp_passwd sp.passwd; > ``` > could be wrong.
I think your analysis is correct. When the memory is owned by C code -- for example, when a C function passes a struct to OCaml with fields already initialized -- then using the string view works well: reading a string field creates an OCaml copy, which persists as long as needed. However, when things are the other way round -- i.e. when you're creating or initializing the struct in OCaml before passing it to C -- then the string view isn't a good choice, because there's no way to manage the lifetime of the C copy of the OCaml string that's written to the struct field. I'm planning to change the interface in a future release to make the lifetime of allocated objects clearer, and to make these kinds of issues less likely. > Is the declaration clearly wrong? How should I declare the strings and > properly copy them between c and ocaml when using ctypes, should they be > char ptr and handled manually? A reasonable way to do this would be to allocate stable memory for the string fields before the C call, and ensure that the memory stays around until the call is complete. Stable memory could mean any of: a bigarray, a Ctypes.CArray.t value, memory returned by malloc, memory returned by Ctypes.allocate, etc. In most of these cases ensuring the memory stays around is a matter of holding onto the handle (bigarray value, Ctypes ptr, etc.) until after the call. Kind regards, Jeremy _______________________________________________ Ctypes mailing list [email protected] http://lists.ocaml.org/listinfo/ctypes
