Skip to content

Commit 3d8535f

Browse files
committed
Fix pointer arguments in addFunction + wasm64
Without this fix, any usages of addFunction - e.g. dylink - would add broken functions to the webassembly table, which result in errors like "Cannot mix BigInt and other types, use explicit conversions" when invoked. To fix this, we need to do essentially the opposite of what we do in `dynCall` and convert all pointer arguments to numbers before invoking the actual JS function, and the pointer result to bigint before returning to wasm.
1 parent 4182f94 commit 3d8535f

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/lib/libaddfunction.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,30 @@ addToLibrary({
9595
#if ASSERTIONS && !WASM_BIGINT
9696
assert(!sig.includes('j'), 'i64 not permitted in function signatures when WASM_BIGINT is disabled');
9797
#endif
98+
99+
#if MEMORY64
100+
// Find all 'p' in the signature, which indicates a pointer we need to convert to/from bigint.
101+
var pReturn = sig[0] == 'p';
102+
var pArgs = [];
103+
for (var i = 1; i < sig.length; ++i) {
104+
if (sig[i] == 'p') {
105+
pArgs.push(i - 1);
106+
}
107+
}
108+
if (pReturn || pArgs.length) {
109+
var origFunc = func;
110+
func = (...args) => {
111+
for (var i of pArgs) {
112+
// Convert the pointer arguments from bigint to number.
113+
args[i] = Number(args[i]);
114+
}
115+
var ret = origFunc(...args);
116+
// Convert the return value from number to bigint if needed.
117+
return pReturn ? BigInt(ret) : ret;
118+
};
119+
}
120+
#endif
121+
98122
#if WASM_JS_TYPES
99123
// If the type reflection proposal is available, use the new
100124
// "WebAssembly.Function" constructor.

test/test_other.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15458,7 +15458,6 @@ def test_add_js_function(self, wasm2js):
1545815458
'memory64': (True, False),
1545915459
'': (False, False),
1546015460
})
15461-
@requires_v8
1546215461
def test_add_js_function_bigint(self, memory64, wasm_function):
1546315462
self.set_setting('WASM_BIGINT')
1546415463

@@ -15491,6 +15490,36 @@ def test_add_js_function_bigint(self, memory64, wasm_function):
1549115490

1549215491
self.do_runf('main.c', '')
1549315492

15493+
@requires_wasm64
15494+
def test_add_js_function_pointers_wasm64(self):
15495+
self.set_setting('MEMORY64')
15496+
self.set_setting('ALLOW_TABLE_GROWTH')
15497+
15498+
create_file('main.c', r'''
15499+
#include <emscripten.h>
15500+
#include <assert.h>
15501+
15502+
EM_JS_DEPS(deps, "$addFunction");
15503+
15504+
typedef void* (functype)(void*);
15505+
15506+
int main() {
15507+
functype* f = EM_ASM_PTR({
15508+
return addFunction((ptr) => {
15509+
return ptr + 1;
15510+
}, 'pp');
15511+
});
15512+
15513+
void* p1 = (void*)26;
15514+
assert(f(p1) == p1 + 1);
15515+
15516+
void* p2 = (void*)493921253191;
15517+
assert(f(p2) == p2 + 1);
15518+
}
15519+
''')
15520+
15521+
self.do_runf('main.c', '')
15522+
1549415523
@parameterized({
1549515524
'': ([],),
1549615525
'pthread': (['-g', '-pthread', '-Wno-experimental', '-sPROXY_TO_PTHREAD', '-sEXIT_RUNTIME'],),

0 commit comments

Comments
 (0)