Skip to content

[js-api] Reject a mutable global import before allocating - #2263

Open
chicoxyzzy wants to merge 2 commits into
WebAssembly:mainfrom
chicoxyzzy:js-api-global-import-mut
Open

chicoxyzzy wants to merge 2 commits into
WebAssembly:mainfrom
chicoxyzzy:js-api-global-import-mut

Conversation

@chicoxyzzy

@chicoxyzzy chicoxyzzy commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Fixes #2253.

read the imports ignored mut and always called global_alloc with const valtype when the value was not a Global. A var import then failed in module_instantiate, and the const global stayed in the store.

Throw a LinkError in that case before allocating. Allocate a fresh global with the import's mut. After that rejection, mut is const.

A Global is passed through. Mutability mismatches stay in module_instantiate, including a const import of a var Global and a var import of a const Global.

The new test covers a const import of a mutable Global for i32, i64, f32, and f64. Instantiation still throws LinkError.

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not also include the case of instantiating a mutable global with an immutable one here? Is there a reason to only support the one direction?

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, actually of course most type validations are left for later, but then the converse point would be -

Rather, why do we need to verify that we are not instantiating an immutable global with a mutable global object here - what makes that case special that it can't also be a deferred validation?

If we removed that, the diff here would drop all the inner |mut| checking for implements Global.

@chicoxyzzy

Copy link
Copy Markdown
Member Author

A var import of a const Global is the same kind of mismatch, and read the imports already leaves it to module_instantiate. Linking rejects it, and instantiate the core of a WebAssembly module throws LinkError. The existing mutable-import test covers that.

The global_type check does not avoid an allocation. The Global is reused, and linking fails the same way. I put it there because the old ESM ExecuteModule path threw before reading the rest of the imports. On this algorithm it is one of the type checks that are supposed to be deferred, same as a later import that allocates only because linking has not failed yet.

The allocation is the other branch: the value does not implement Global and mut is var. global_alloc runs inside read the imports, and that global stays in the store after linking fails. That LinkError stays.

I'll remove the global_type check. global_alloc then only runs for a const import, still with that import's mut. The new test still expects LinkError, from instantiation.

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While not a bug or major correctness issue, the risk of this is relatively low, and it ensures better hygiene by avoiding an unnecessary global store.

Formally, making the LinkError earlier for this case is an error ordering change, but we don't see strict error ordering in implementations currently anyway - for example, V8 doesn't respect error ordering per the spec (Get's enumerate first in a batch instead of interleaving validation).

LGTM

@chicoxyzzy
chicoxyzzy force-pushed the js-api-global-import-mut branch from 24b9ae6 to 0902790 Compare October 12, 2026 21:01
Fixes WebAssembly#2253.

A non-Global value for a var import was passed to global_alloc as a
const global. module_instantiate then rejected the mutability mismatch
and left that global in the store. Throw a LinkError before allocating.

A const import of a var Global is the same mismatch. Throw before
appending that global. A fresh global is allocated with the import's
mut, which is const once the var case has been rejected.
read the imports does not call global_type. A const import of a var
Global allocates nothing, and module_instantiate already rejects both
mutability mismatches. The LinkError before global_alloc stays when a
var import's value is not a Global.
@chicoxyzzy
chicoxyzzy force-pushed the js-api-global-import-mut branch from 0902790 to 2d1268d Compare October 15, 2026 16:01
@chicoxyzzy

Copy link
Copy Markdown
Member Author

rebased onto main

This branch has not been deployed

No deployments
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.

[js-api] A mutable global import allocates a const global before LinkError

2 participants