Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special constructor for %sys_argv primitive #10570

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

Keryan-dev
Copy link
Contributor

This fixes a bug in the case caml_sys_argv would be called directly by the user.

external argv :  _ -> _ = "caml_sys_argv"

This would end up as a function with two arguments because it would get caught in the special case of

ocaml/lambda/translprim.ml

Lines 651 to 652 in 7f58ef0

| External prim, args when prim = prim_sys_argv ->
Lprim(Pccall prim, Lconst (const_int 0) :: args, loc)

that was meant to handle %sys_argv.
Somehow, the additional argument doesn't seem to bother the compiler but it might lead to runtime errors.

The additional constructor avoid this by allowing caml_sys_argv to be handled as any other C call.

@lthls
Copy link
Contributor

lthls commented Aug 17, 2021

To reproduce the bug:

# external f : unit -> string array = "caml_sys_argv";;
external f : unit -> string array = "caml_sys_argv"
# let _ = f ();;
Segmentation fault

This caused a compilation failure in the obytelib library when compiling with Flambda 2 (which depends more strictly on the primitive arities). A pull request has already been made there to work around this issue (bvaugon/obytelib#5).

@xavierleroy
Copy link
Contributor

Playing devil's advocate:

Mis-using a %prim primitive can cause all sorts of run-time crashes. It's an unsafe feature that no amount of hacking on the compiler will make safe. Why focus on this run-time crash in particular?

Suggesting a simpler fix: in the current code it might work to just ignore the extra arguments:

- Lprim(Pccall prim, Lconst (const_int 0) :: args, loc)
+ Lprim(Pccall prim, [Lconst (const_int 0)], loc)

@Keryan-dev
Copy link
Contributor Author

Playing deviler advocate:
Should the user want to have side effects in those arguments, would we just ignore those for this particular primitive ?

@lthls
Copy link
Contributor

lthls commented Aug 26, 2021

To clarify a bit:

  • We haven't actually observed a runtime crash in the wild.
  • What we observed is a mismatch in the backend between the declared arity of a C primitive and the number of arguments it is given (in Lambda terms, that would have been Lprim (Pccall { prim_arity = 1; _}, [arg1; arg2], _)). The code in Flambda 2 is less forgiving of this kind of errors than the current compiler, so this leads to a compilation error.
  • The only code we've seen that actually exports caml_sys_argv as an external (and not the %sys_argv primitive) is obytelib, and it does it by re-exporting (almost) all the primitives returned by ocamlrun -p. We've already suggested a patch to special-case caml_sys_argv.

This patch does not fix a real bug, but brings consistency to the code translating external primitives so we thought it was worth submitting as a PR here in addition to the PR on the Flambda 2 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants