Skip to content

4.14.0: segfault in bytecode interpreter with nnp and lots of global data #11768

@emillon

Description

@emillon

Hello,

I received this bug report regarding utop. After trying to reproduce the issue, there's an issue with how the bytecode interpreter handles global data when --disable-naked-pointers is set.

  • this happens on 4.14.0 but not in 5.0.0~beta2
  • this only happens when --disable-naked-pointers is set. (the nnp checker does not detect this)
  • this happens when there's a certain amount of global data to load (this was found when we moved from camomile to uucp which uses large strings as globals)

Here's a simple reproduction case. The following generates a program that when built as bytecode, will trigger a segfault.

let blank = String.make 10_000_000 ' '
let () = Printf.printf "let _ = \"%s\"\n" blank

It's also possible to generate a greater amount of shorter strings, which I suppose is more representative:

let blank = String.make 1000 ' '

let () =
  for _ = 1 to 10000 do
    Printf.printf "let _ = \"%s\"\n" blank
  done

(going in the other direction of trying to generate many very small strings triggers a stack overflow in the compiler but I know that it's not a goal to support this)

The resulting stacktrace (of ocamlrun) is:

#0  caml_darken (v=0, p=0x5555555a45c0 <caml_global_data>) at major_gc.c:285
#1  0x000055555558f5a4 in caml_do_roots (f=0x55555558d4b0 <caml_darken>, 
    do_globals=<optimized out>) at roots_byt.c:91
#2  0x000055555558f611 in caml_darken_all_roots_start () at roots_byt.c:75
#3  0x000055555558df0f in start_cycle () at major_gc.c:407
#4  caml_major_collection_slice (howmuch=howmuch@entry=-1) at major_gc.c:1089
#5  0x000055555558f18d in caml_gc_dispatch () at minor_gc.c:500
#6  0x000055555558f259 in caml_check_urgent_gc (extra_root=<optimized out>, extra_root@entry=1)
    at minor_gc.c:575
#7  0x000055555556c098 in caml_do_pending_actions_exn () at signals.c:267
#8  0x000055555556c37b in process_pending_actions_with_root_exn (extra_root=<optimized out>)
    at signals.c:299
#9  caml_process_pending_actions () at signals.c:331
#10 0x0000555555576c1b in intern_end (res=<optimized out>, whsize=<optimized out>)
    at intern.c:709
#11 0x0000555555577837 in caml_input_val (chan=chan@entry=0x5555555ecd70) at intern.c:808
#12 0x000055555558a1ee in caml_main (argv=0x7fffffffde78) at startup_byt.c:570
#13 0x000055555556979c in main (argc=<optimized out>, argv=<optimized out>) at main.c:37

The end of the output of dumpobj is:

File "_none_", line 0, characters -1--1:
    2794  POP 89
    2796  SETGLOBAL Stdlib
    2798  GETGLOBAL <string of length 10000000>
File "_none_", line 0, characters -1--1:
    2800  ATOM0
File "_none_", line 0, characters -1--1:
    2801  SETGLOBAL Dune__exe__Generated
    2803  CONST0
    2804  PUSHGETGLOBALFIELD Stdlib, 102
    2807  APPLY1
File "std_exit.ml", line 18, characters 8-20:
    2808  ATOM0
File "_none_", line 0, characters -1--1:
    2809  SETGLOBAL Std_exit
    2811  STOP

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions