Skip to content

Bug in handling of mutable variables in Cmm #13875

Description

@lthls

As noted in #12466 (comment), the bind function in Cmm_helpers doesn't properly protect against reads of mutable variables. It took me a while to find a way to exploit that, but I finally got it using method calls.
Here is an example:

let () =
  let o1 = object val x = 0 method get () = x end in
  let o2 = object method get () = 1 end in
  let r = ref o1 in
  let n = (!r)#get (r := o2) in
  print_int n; print_newline ()

The assignment will be evaluated between a piece of code that gets the actual method, and the piece that calls it, the the method gets an object different from the one it is expecting. In this particular example, we retrieve the method get from o1, pass it o2, and then we read whatever garbage happens to be stored where x would be if o2 had the same layout as o1.

Note that the issue is very unlikely to come up in practice. First, it requires the Closure middle-end (Flambda enforces a proper evaluation order before going to Cmm). In addition, the method call has to be at toplevel (so that it doesn't use the cached method call version, which only has one occurrence of the object under the bind). And of course a local reference has to be involved, which combined with the toplevel requirement and Closure's compilation strategy for toplevel bindings, means that this can only be inside the definition of a non-function toplevel binding. Finally, the reference holding the object has to be modified in one of the arguments to the function call.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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