Skip to content

[BUG] marshal.js: caml_output_val is incorrect? #1456

@david-maison-TrustInSoft

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions