Skip to content

Compartmentalizing unsafe from managed code #709

@dcodeIO

Description

@dcodeIO

With current master it is possible to mix unsafe and managed code at will, which can lead to all sorts of issues where unsafe code corrupts managed state. To account for this, it has been suggested to add a mechanism to either allow or disallow the mixing.

As ever so often, there are two perspectives to this.

  1. Once WebAssembly GC lands it can be expected that if everything becomes a managed object, unsafe code will not be able to interfere with its internals, and if it is possible to model the entire runtime on top of safe WebAssembly features that'll make the restrictions unnecessary.

  2. At this point, though, with the runtime living in linear memory alongside user code, there'll be use cases where an engine wants to restrict a user in a way that he cannot accidentally break it. It can also be expected that the runtime will stick around even if WebAssembly GC lands, to support environments that don't provide GC.

Hence I suggest to add a new compiler flag --allow-unsafe that is equivalent to the current behavior, a new compiler flag --disallow-unsafe that disallows the use of anything potentially unsafe in user code and a new default that acts like --allow-unsafe but emits warnings on unsafe code, essentially hinting a user into either using the --allow-unsafe or the --disallow-unsafe flag.

Standard library code would not have this restriction since it cannot implement anything without resorting to unsafe code. One detail here is that, currently, the only files being considered as stdlib files are the top-level files in lib directories, so I suggest to make the top-level files essentially contagious, so that every file imported from a stdlib file becomes a stdlib file as well.

For an implementer, allowing unsafe code in lib files means that, under the --disallow-unsafe condition, it is still possible to add unsafe code as library files using the --lib option, for example to more efficiently implement custom collections etc.

Open questions:

  • What should the compiler do if an external module, for instance a JSON parser, that is being imported relies on unsafe code? Should this always be disallowed or allowed depending on the flag, should it exclude any modules imports from the check, or should there be an option to define this on a per module basis?
  • Do we need a mechanism to annotate unsafe code, like being able to declare an unsafe block of statements? How would this integrate with the proposed compiler options?

As of the respective meta issue, this should probably become our first RFC.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions