Skip to content

Commit 3f3fc85

Browse files
authored
Fix fuzzing JS glue code (#1843)
After we added logging to the fuzzer, we forgot to add to the JS glue code the necessary imports so it can be run there too. Also adds legalization for the JS glue code imports and exports. Also adds a missing validator check on imports having a function type (the fuzzing code was missing one). Fixes #1842
1 parent fdd4cb7 commit 3f3fc85

File tree

6 files changed

+115
-12
lines changed

6 files changed

+115
-12
lines changed

src/tools/fuzzing.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ class TranslateToFuzzReader {
314314
func->base = name;
315315
func->params.push_back(type);
316316
func->result = none;
317+
func->type = ensureFunctionType(getSig(func), &wasm)->name;
317318
wasm.addFunction(func);
318319
}
319320
}

src/tools/js-wrapper.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,15 @@
2222
namespace wasm {
2323

2424
static std::string generateJSWrapper(Module& wasm) {
25+
PassRunner runner(&wasm);
26+
runner.add("legalize-js-interface");
27+
runner.run();
28+
2529
std::string ret;
2630
ret += "if (typeof console === 'undefined') {\n"
2731
" console = { log: print };\n"
2832
"}\n"
33+
"var tempRet0;\n"
2934
"var binary;\n"
3035
"if (typeof process === 'object' && typeof require === 'function' /* node.js detection */) {\n"
3136
" var args = process.argv.slice(2);\n"
@@ -44,7 +49,18 @@ static std::string generateJSWrapper(Module& wasm) {
4449
" binary = read(args[0], 'binary');\n"
4550
" }\n"
4651
"}\n"
47-
"var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {});\n";
52+
"var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {\n"
53+
" 'fuzzing-support': {\n"
54+
" 'log-i32': function(x) { console.log('i32: ' + x) },\n"
55+
" 'log-i64': function(x, y) { console.log('i64: ' + x + ', ' + y) },\n"
56+
" 'log-f32': function(x) { console.log('f32: ' + x) },\n"
57+
" 'log-f64': function(x) { console.log('f64: ' + x) }\n"
58+
" },\n"
59+
" 'env': {\n"
60+
" 'setTempRet0': function(x) { tempRet0 = x },\n"
61+
" 'getTempRet0': function() { return tempRet0 },\n"
62+
" },\n"
63+
"});\n";
4864
for (auto& exp : wasm.exports) {
4965
auto* func = wasm.getFunctionOrNull(exp->value);
5066
if (!func) continue; // something exported other than a function

src/wasm/wasm-validator.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,9 @@ void FunctionValidator::visitFunction(Function* curr) {
10691069
shouldBeTrue(ft->params == curr->params, curr->name, "function params must match its declared type");
10701070
shouldBeTrue(ft->result == curr->result, curr->name, "function result must match its declared type");
10711071
}
1072+
if (curr->imported()) {
1073+
shouldBeTrue(curr->type.is(), curr->name, "imported functions must have a function type");
1074+
}
10721075
}
10731076

10741077
static bool checkOffset(Expression* curr, Address add, Address max) {

test/passes/emit-js-wrapper=a.js.txt

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,93 @@
44
(type $2 (func (param i32 i64 f32 f64)))
55
(type $3 (func (param i32 f32 f64)))
66
(type $4 (func (param i32 f32 f64) (result i64)))
7+
(type $FUNCSIG$vi (func (param i32)))
8+
(import "env" "setTempRet0" (func $setTempRet0 (param i32)))
79
(memory $0 256 256)
810
(export "add" (func $add))
911
(export "no_return" (func $no-return))
10-
(export "types" (func $types))
11-
(export "types2" (func $types2))
12-
(export "types3" (func $types3))
13-
(func $add (; 0 ;) (type $0) (param $x i32) (param $y i32) (result i32)
12+
(export "types" (func $legalstub$types))
13+
(export "types2" (func $legalstub$types2))
14+
(export "types3" (func $legalstub$types3))
15+
(func $add (; 1 ;) (type $0) (param $x i32) (param $y i32) (result i32)
1416
(i32.add
1517
(get_local $x)
1618
(get_local $y)
1719
)
1820
)
19-
(func $unexported (; 1 ;) (type $0) (param $x i32) (param $y i32) (result i32)
21+
(func $unexported (; 2 ;) (type $0) (param $x i32) (param $y i32) (result i32)
2022
(i32.add
2123
(get_local $x)
2224
(get_local $y)
2325
)
2426
)
25-
(func $no-return (; 2 ;) (type $1) (param $x i32)
27+
(func $no-return (; 3 ;) (type $1) (param $x i32)
2628
(drop
2729
(i32.add
2830
(get_local $x)
2931
(get_local $x)
3032
)
3133
)
3234
)
33-
(func $types (; 3 ;) (type $2) (param $x i32) (param $y i64) (param $z f32) (param $w f64)
35+
(func $types (; 4 ;) (type $2) (param $x i32) (param $y i64) (param $z f32) (param $w f64)
3436
(nop)
3537
)
36-
(func $types2 (; 4 ;) (type $3) (param $x i32) (param $z f32) (param $w f64)
38+
(func $types2 (; 5 ;) (type $3) (param $x i32) (param $z f32) (param $w f64)
3739
(nop)
3840
)
39-
(func $types3 (; 5 ;) (type $4) (param $x i32) (param $z f32) (param $w f64) (result i64)
41+
(func $types3 (; 6 ;) (type $4) (param $x i32) (param $z f32) (param $w f64) (result i64)
4042
(i64.const 1)
4143
)
44+
(func $legalstub$types (; 7 ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 f64) (param $4 f64)
45+
(call $types
46+
(get_local $0)
47+
(i64.or
48+
(i64.extend_u/i32
49+
(get_local $1)
50+
)
51+
(i64.shl
52+
(i64.extend_u/i32
53+
(get_local $2)
54+
)
55+
(i64.const 32)
56+
)
57+
)
58+
(f32.demote/f64
59+
(get_local $3)
60+
)
61+
(get_local $4)
62+
)
63+
)
64+
(func $legalstub$types2 (; 8 ;) (param $0 i32) (param $1 f64) (param $2 f64)
65+
(call $types2
66+
(get_local $0)
67+
(f32.demote/f64
68+
(get_local $1)
69+
)
70+
(get_local $2)
71+
)
72+
)
73+
(func $legalstub$types3 (; 9 ;) (param $0 i32) (param $1 f64) (param $2 f64) (result i32)
74+
(local $3 i64)
75+
(set_local $3
76+
(call $types3
77+
(get_local $0)
78+
(f32.demote/f64
79+
(get_local $1)
80+
)
81+
(get_local $2)
82+
)
83+
)
84+
(call $setTempRet0
85+
(i32.wrap/i64
86+
(i64.shr_u
87+
(get_local $3)
88+
(i64.const 32)
89+
)
90+
)
91+
)
92+
(i32.wrap/i64
93+
(get_local $3)
94+
)
95+
)
4296
)

test/passes/emit-js-wrapper=a.js.wast.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
if (typeof console === 'undefined') {
22
console = { log: print };
33
}
4+
var tempRet0;
45
var binary;
56
if (typeof process === 'object' && typeof require === 'function' /* node.js detection */) {
67
var args = process.argv.slice(2);
@@ -19,7 +20,18 @@ if (typeof process === 'object' && typeof require === 'function' /* node.js dete
1920
binary = read(args[0], 'binary');
2021
}
2122
}
22-
var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {});
23+
var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {
24+
'fuzzing-support': {
25+
'log-i32': function(x) { console.log('i32: ' + x) },
26+
'log-i64': function(x, y) { console.log('i64: ' + x + ', ' + y) },
27+
'log-f32': function(x) { console.log('f32: ' + x) },
28+
'log-f64': function(x) { console.log('f64: ' + x) }
29+
},
30+
'env': {
31+
'setTempRet0': function(x) { tempRet0 = x },
32+
'getTempRet0': function() { return tempRet0 },
33+
},
34+
});
2335
if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();
2436
try {
2537
console.log('calling: add');
@@ -35,10 +47,24 @@ instance.exports.no_return(0);
3547
console.log(' exception: ' + e);
3648
}
3749
if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();
50+
try {
51+
console.log('calling: types');
52+
instance.exports.types(0, 0, 0, 0, 0);
53+
} catch (e) {
54+
console.log(' exception: ' + e);
55+
}
56+
if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();
3857
try {
3958
console.log('calling: types2');
4059
instance.exports.types2(0, 0, 0);
4160
} catch (e) {
4261
console.log(' exception: ' + e);
4362
}
63+
if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();
64+
try {
65+
console.log('calling: types3');
66+
console.log(' result: ' + instance.exports.types3(0, 0, 0));
67+
} catch (e) {
68+
console.log(' exception: ' + e);
69+
}
4470
console.log('done.')

test/passes/translate-to-fuzz.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
(module
2+
(type $FUNCSIG$vi (func (param i32)))
3+
(type $FUNCSIG$vj (func (param i64)))
4+
(type $FUNCSIG$vf (func (param f32)))
5+
(type $FUNCSIG$vd (func (param f64)))
26
(type $FUNCSIG$v (func))
37
(type $FUNCSIG$jddfiV (func (param f64 f64 f32 i32 v128) (result i64)))
48
(type $FUNCSIG$viViVjV (func (param i32 v128 i32 v128 i64 v128)))
5-
(type $FUNCSIG$vd (func (param f64)))
69
(type $FUNCSIG$VVVVVii (func (param v128 v128 v128 v128 i32 i32) (result v128)))
710
(type $FUNCSIG$fddffj (func (param f64 f64 f32 f32 i64) (result f32)))
811
(type $FUNCSIG$j (func (result i64)))

0 commit comments

Comments
 (0)