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

non-writable property on Object.prototype prevents linking WebAssembly module #749

Closed
bakkot opened this issue Aug 2, 2023 · 2 comments
Closed
Assignees
Labels
bug Something isn't working

Comments

@bakkot
Copy link

bakkot commented Aug 2, 2023

Version: 22.3.3

The following program throws "LinkError: Object does not contain member fn":

String source = "Object.defineProperty(Object.prototype, 'extern_module', { value: null, writable: false });\n" +
	"var bytes = new Uint8Array([0,97,115,109,1,0,0,0,1,8,2,96,1,127,0,96,0,0,2,20,1,13,101,120,116,101,114,110,95,109,111,100,117,108,101,2,102,110,0,0,3,2,1,1,8,1,1,10,8,1,6,0,65,1,16,0,11,0,26,4,110,97,109,101,1,12,2,0,3,102,110,49,1,4,109,97,105,110,2,5,2,0,0,1,0]);\n" +
	"var wasmModule = new WebAssembly.Module(bytes);\n" +
	"var jsApi = { fn(a) { console.log(a) } };\n" +
	"console.log(typeof jsApi.fn === 'function');\n" +
	"var imports = { extern_module: jsApi };\n" +
	"console.log(imports.extern_module === jsApi);\n" +
	"new WebAssembly.Instance(wasmModule, imports);\n";

Context context = Context.newBuilder("wasm", "js")
	.allowExperimentalOptions(true)
	.allowPolyglotAccess(PolyglotAccess.ALL)
	.option("js.webassembly", "true")
	.build();

try (context) {
	context.eval("js", source);
}

But it shouldn't - if you run the same source in a browser you'll get no error.

The wasm program whose bytes are in that array is

(module
  (import "extern_module" "fn" (func $fn1 (param i32) (result)))
  (func $main (param) (result)
    (call $fn1 (i32.const 1))
  )
  (start $main)
 )

Probably there's some JS code doing something like let x = {}; x[moduleName] = y;, which will fail when moduleName is a non-writable property on Object.prototype - this is a stupid corner of JS semantics, but also, you probably shouldn't have runtime-internal code use the user-exposed Object.prototype.

cc @michaelficarra

@iamstolis
Copy link
Member

Thank you for the report.

Probably there's some JS code doing something like let x = {}; x[moduleName] = y;

Yes, there is something like this in our handling of the import object. And yes, the usage of Object.prototype is not intentional here, the object x should have been created with null prototype.

@iamstolis iamstolis self-assigned this Aug 3, 2023
@iamstolis iamstolis added the bug Something isn't working label Aug 3, 2023
@iamstolis
Copy link
Member

Fixed by e59a262

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants