-
Notifications
You must be signed in to change notification settings - Fork 197
Description
Describe the bug
In version 4.0.0, we were successfully using js_of_ocaml to marshal data in Javascript (running inside a web browser), and unmarshalling data inside a "pure" OCaml program.
While trying to upgrade to version 5.1.1, something went wrong while unmarshalling the same data. The "pure" OCaml program segfault.
So first question: can we still expect to use marshal in such a use case? Or do you expect the result of Marshal.to_string to be only used in a Javascript world (i.e. by runtime/marshal.js)?
If we can still expect such a use case, here is a small repro case:
#!/bin/bash
set -Eeuo pipefail
cd "$(mktemp -d)"
cat > "dune-project" <<EOF
(lang dune 2.7)
EOF
cat > "dune" <<EOF
(executable (name out) (modes js) (modules out))
(executable (name out_nojs) (modules out_nojs))
(executable (name in) (modules in))
EOF
cat > "out.ml" <<EOF
type t = (string * string) list
let s = "poi"
let p = (s, s)
let obj : t = [ p; p ]
let () = print_endline (Marshal.to_string obj [])
EOF
# Create out_nojs.ml to compare the behavior of the same program
# without using js_of_ocaml.
ln -s out.ml out_nojs.ml
cat > "in.ml" <<EOF
type t = (string * string) list
let l : t = Marshal.from_channel stdin
let () =
List.iter
(fun (a, b) -> Format.printf "%s - %s@." a b)
l
EOF
dune build
echo "Output is different (but maybe not a problem?)"
nodejs _build/default/out.bc.js | hexdump
_build/default/out_nojs.exe | hexdump
echo "Without using js_of_ocaml: normal expected behavior"
_build/default/out_nojs.exe | _build/default/in.exe
echo "With js_of_ocaml: segfault during Marshal.from_channel"
nodejs _build/default/out.bc.js | _build/default/in.exe
The output of the above script should be something similar to:
Output is different (but maybe not a problem?)
0000000 9584 bea6 0000 0e00 0000 0300 0000 0d00
0000010 0000 0d00 a0a0 7023 696f 7023 696f 04a0
0000020 4002 000a
0000023
0000000 9584 bea6 0000 0c00 0000 0400 0000 0b00
0000010 0000 0b00 a0a0 7023 696f 0104 04a0 4003
0000020 000a
0000021
Without using js_of_ocaml: normal expected behavior
poi - poi
poi - poi
With js_of_ocaml: segfault during Marshal.from_channel
poi - poi
run.sh: line 48: 3045646 Done nodejs _build/default/out.bc.js
3045647 Segmentation fault | _build/default/in.exe
Expected behavior
The expected behavior is to be able to successfully unmarshal the data in the "pure" OCaml program.
Additional information
The problem does not exist if the Marshal.No_sharing flag is given to Marshal.to_string.
Note: you can ignore the following paragraph if you want.
In our real use case, the segfault is slightly different from the repro case above:
[...]
malloc(): invalid size (unsorted)
Aborted
And while inspecting the marshaled string, the only difference between js_of_ocaml 4.0.0 and 5.1.1 is located on the first bytes:
-00000000: 8495 a6be 0000 024f 0000 0014 0000 00d6 .......O........
+00000000: 8495 a6be 0000 024f 0000 001f 0000 00d6 .......O........
Versions
dune: 3.7.1
ocamlc: 4.14.1
js_of_ocaml: 5.1.1