Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshal and magic_copy in js_of_ocaml

Newbie question. I'm going through the very nice Ocaml ORA book. When I went to play with the magic_copy example from the section on Marshal, I was closer to a browser than a terminal, so I tried it out in ocsigen's toplevel in a browser, where I was surprised to get the result:

     (* js_of_ocaml *)
# let ora_magic_copy a =
  let s = Marshal.to_string a [Marshal.Closures] in
  Marshal.from_string s 0;;

val ora_magic_copy : 'a -> 'b = <fun>
# (ora_magic_copy 2 : float) +. 3.1;;

- : float = 5.1

Checking if something has changed between ocaml 2 (current version when the book was written) and ocaml 3.12.1, used by the toplevel installed on my machine and by js_of_ocaml, I tried the same example in the normal toplevel installed on my machine and got the result explained in the book: a segfault due to the typesystem's trouble with checking Marshaled values.

    (* Linux toplevel *)
# (ora_magic_copy 3: float) +. 2.1;;
Segmentation fault (core dumped)

I'm just curious: why?

I see that in three cases, Marshal.to_string gives the same string: linux marshalling an int, js_of_ocaml marshalling and int, js_of_ocaml marshalling a float. The odd-man-out is linux toplevel marshalling a float.

Is this due to something about js_of_ocaml using javascript's base types? Or just... undefined behavior?

like image 685
ImAlsoGreg Avatar asked Sep 09 '12 22:09

ImAlsoGreg


1 Answers

Yes, your problem comes from the fact that you are testing on a javascript toplevel.

When you use the standard ocaml toplevel, the +. operation operates on OCaml floats, i.e. a double boxed inside a block, the two parameters of +. are expected to be pointers to such boxes. In your example, instead of a pointer, you give the OCaml integer 2 (internally, it is represented as 5, i.e. 2 << 1 + 1), so OCaml segfaults while trying to read the double that should be at position 0x5 in memory...

In the js_of_ocaml browser, floats are just javascript floats, and integers are javascript integers, and +. is the javascript addition, which is able to add integers and floats (by automatically converting integers to floats), because values are tagged by their types.

like image 60
Fabrice Le Fessant Avatar answered Feb 08 '23 02:02

Fabrice Le Fessant