Skip to content

Commit 5f2dd57

Browse files
committed
Merge remote-tracking branch 'origin/master' into fuzz
2 parents bfdbc0c + 76751bf commit 5f2dd57

7 files changed

Lines changed: 484 additions & 1 deletion

src/wasm/wasm-binary.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,16 @@ void WasmBinaryWriter::visitBreak(Break *curr) {
648648
if (curr->condition) recurse(curr->condition);
649649
o << int8_t(curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br)
650650
<< U32LEB(getBreakIndex(curr->name));
651+
if (curr->condition && curr->type == unreachable) {
652+
// a br_if is normally none or emits a value. if it is unreachable,
653+
// then either the condition or the value is unreachable, which is
654+
// extremely rare, and may require us to make the stack polymorphic
655+
// (if the block we branch to has a value, we may lack one as we
656+
// are not a taken branch; the wasm spec on the other hand does
657+
// presume the br_if emits a value of the right type, even if it
658+
// popped unreachable)
659+
o << int8_t(BinaryConsts::Unreachable);
660+
}
651661
}
652662

653663
void WasmBinaryWriter::visitSwitch(Switch *curr) {
@@ -669,6 +679,9 @@ void WasmBinaryWriter::visitCall(Call *curr) {
669679
recurse(operand);
670680
}
671681
o << int8_t(BinaryConsts::CallFunction) << U32LEB(getFunctionIndex(curr->target));
682+
if (curr->type == unreachable) {
683+
o << int8_t(BinaryConsts::Unreachable);
684+
}
672685
}
673686

674687
void WasmBinaryWriter::visitCallImport(CallImport *curr) {
@@ -689,6 +702,9 @@ void WasmBinaryWriter::visitCallIndirect(CallIndirect *curr) {
689702
o << int8_t(BinaryConsts::CallIndirect)
690703
<< U32LEB(getFunctionTypeIndex(curr->fullType))
691704
<< U32LEB(0); // Reserved flags field
705+
if (curr->type == unreachable) {
706+
o << int8_t(BinaryConsts::Unreachable);
707+
}
692708
}
693709

694710
void WasmBinaryWriter::visitGetLocal(GetLocal *curr) {
@@ -700,6 +716,9 @@ void WasmBinaryWriter::visitSetLocal(SetLocal *curr) {
700716
if (debug) std::cerr << "zz node: Set|TeeLocal" << std::endl;
701717
recurse(curr->value);
702718
o << int8_t(curr->isTee() ? BinaryConsts::TeeLocal : BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->index]);
719+
if (curr->type == unreachable) {
720+
o << int8_t(BinaryConsts::Unreachable);
721+
}
703722
}
704723

705724
void WasmBinaryWriter::visitGetGlobal(GetGlobal *curr) {
@@ -986,6 +1005,9 @@ void WasmBinaryWriter::visitUnary(Unary *curr) {
9861005
case ReinterpretInt64: o << int8_t(BinaryConsts::F64ReinterpretI64); break;
9871006
default: abort();
9881007
}
1008+
if (curr->type == unreachable) {
1009+
o << int8_t(BinaryConsts::Unreachable);
1010+
}
9891011
}
9901012

9911013
void WasmBinaryWriter::visitBinary(Binary *curr) {
@@ -1075,6 +1097,9 @@ void WasmBinaryWriter::visitBinary(Binary *curr) {
10751097
case GeFloat64: o << int8_t(BinaryConsts::F64Ge); break;
10761098
default: abort();
10771099
}
1100+
if (curr->type == unreachable) {
1101+
o << int8_t(BinaryConsts::Unreachable);
1102+
}
10781103
}
10791104

10801105
void WasmBinaryWriter::visitSelect(Select *curr) {
@@ -1083,6 +1108,9 @@ void WasmBinaryWriter::visitSelect(Select *curr) {
10831108
recurse(curr->ifFalse);
10841109
recurse(curr->condition);
10851110
o << int8_t(BinaryConsts::Select);
1111+
if (curr->type == unreachable) {
1112+
o << int8_t(BinaryConsts::Unreachable);
1113+
}
10861114
}
10871115

10881116
void WasmBinaryWriter::visitReturn(Return *curr) {
@@ -1771,7 +1799,11 @@ Expression* WasmBinaryBuilder::popExpression() {
17711799
throw ParseException("attempted pop from empty stack");
17721800
}
17731801
auto ret = expressionStack.back();
1774-
expressionStack.pop_back();
1802+
// to simulate the wasm polymorphic stack mode, leave a final
1803+
// unreachable, don't empty the stack in that case
1804+
if (!(expressionStack.size() == 1 && ret->type == unreachable)) {
1805+
expressionStack.pop_back();
1806+
}
17751807
return ret;
17761808
}
17771809

test/polymorphic_stack.wast

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
(module
2+
(type $FUNCSIG$ii (func (param i32) (result i32)))
3+
(import "env" "table" (table 9 9 anyfunc))
4+
(func $break-and-binary (result i32)
5+
(block $x (result i32)
6+
(f32.add
7+
(br_if $x
8+
(i32.trunc_u/f64
9+
(unreachable)
10+
)
11+
(i32.trunc_u/f64
12+
(unreachable)
13+
)
14+
)
15+
(f32.const 1)
16+
)
17+
)
18+
)
19+
(func $call-and-unary (param i32) (result i32)
20+
(drop
21+
(i64.eqz
22+
(call $call-and-unary
23+
(unreachable)
24+
)
25+
)
26+
)
27+
(drop
28+
(i64.eqz
29+
(i32.eqz
30+
(unreachable)
31+
)
32+
)
33+
)
34+
(drop
35+
(i64.eqz
36+
(call_indirect $FUNCSIG$ii
37+
(unreachable)
38+
(unreachable)
39+
)
40+
)
41+
)
42+
)
43+
(func $tee (param $x i32)
44+
(local $y f32)
45+
(drop
46+
(i64.eqz
47+
(tee_local $x
48+
(unreachable)
49+
)
50+
)
51+
)
52+
(drop
53+
(tee_local $y
54+
(i64.eqz
55+
(unreachable)
56+
)
57+
)
58+
)
59+
)
60+
(func $tee2
61+
(local $0 f32)
62+
(if
63+
(i32.const 259)
64+
(set_local $0
65+
(unreachable)
66+
)
67+
)
68+
)
69+
(func $select
70+
(drop
71+
(i64.eqz
72+
(select
73+
(unreachable)
74+
(i32.const 1)
75+
(i32.const 2)
76+
)
77+
)
78+
)
79+
)
80+
(func $untaken-break-should-have-value (result i32)
81+
(block $x (result i32)
82+
(block
83+
(br_if $x ;; ok to not have a value, since an untaken branch. but must emit valid binary for wasm
84+
(unreachable)
85+
)
86+
)
87+
)
88+
)
89+
)
90+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
(module
2+
(type $FUNCSIG$ii (func (param i32) (result i32)))
3+
(type $1 (func (result i32)))
4+
(type $2 (func (param i32)))
5+
(type $3 (func))
6+
(import "env" "table" (table 9 9 anyfunc))
7+
(memory $0 0)
8+
(func $break-and-binary (type $1) (result i32)
9+
(block $x (result i32)
10+
(f32.add
11+
(br_if $x
12+
(i32.trunc_u/f64
13+
(unreachable)
14+
)
15+
(i32.trunc_u/f64
16+
(unreachable)
17+
)
18+
)
19+
(f32.const 1)
20+
)
21+
)
22+
)
23+
(func $call-and-unary (type $FUNCSIG$ii) (param $0 i32) (result i32)
24+
(drop
25+
(i64.eqz
26+
(call $call-and-unary
27+
(unreachable)
28+
)
29+
)
30+
)
31+
(drop
32+
(i64.eqz
33+
(i32.eqz
34+
(unreachable)
35+
)
36+
)
37+
)
38+
(drop
39+
(i64.eqz
40+
(call_indirect $FUNCSIG$ii
41+
(unreachable)
42+
(unreachable)
43+
)
44+
)
45+
)
46+
)
47+
(func $tee (type $2) (param $x i32)
48+
(local $y f32)
49+
(drop
50+
(i64.eqz
51+
(tee_local $x
52+
(unreachable)
53+
)
54+
)
55+
)
56+
(drop
57+
(tee_local $y
58+
(i64.eqz
59+
(unreachable)
60+
)
61+
)
62+
)
63+
)
64+
(func $tee2 (type $3)
65+
(local $0 f32)
66+
(if
67+
(i32.const 259)
68+
(tee_local $0
69+
(unreachable)
70+
)
71+
)
72+
)
73+
(func $select (type $3)
74+
(drop
75+
(i64.eqz
76+
(select
77+
(unreachable)
78+
(i32.const 1)
79+
(i32.const 2)
80+
)
81+
)
82+
)
83+
)
84+
(func $untaken-break-should-have-value (type $1) (result i32)
85+
(block $x (result i32)
86+
(block $block
87+
(br_if $x
88+
(unreachable)
89+
)
90+
)
91+
)
92+
)
93+
)

0 commit comments

Comments
 (0)