diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-11-09 15:09:34 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-09 15:09:34 -0800 |
commit | 566e2c15016cbcf45dfa844ef2788ce27cdfab6f (patch) | |
tree | 645c96ac9e50e37d2d237cde747b1030f6501657 | |
parent | 83f62325ac33706b1fcc589bc5ad6e290ed14d3f (diff) | |
download | binaryen-566e2c15016cbcf45dfa844ef2788ce27cdfab6f.tar.gz binaryen-566e2c15016cbcf45dfa844ef2788ce27cdfab6f.tar.bz2 binaryen-566e2c15016cbcf45dfa844ef2788ce27cdfab6f.zip |
Rereloop fuzz fix (#1259)
* fix relooper bug, ensure function body has right type, as relooper output does not flow stuff out, but wasm functions with a result do expect a flow value, so none is not an option. in other words, as the docs say, a relooper block must end with a terminator (return, unreachable, break, etc.) and not flow out.
-rw-r--r-- | src/passes/ReReloop.cpp | 12 | ||||
-rw-r--r-- | test/passes/flatten_rereloop.txt | 82 | ||||
-rw-r--r-- | test/passes/flatten_rereloop.wast | 24 | ||||
-rw-r--r-- | test/passes/rereloop.txt | 39 |
4 files changed, 139 insertions, 18 deletions
diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp index 99e60a72f..ff1eec6b5 100644 --- a/src/passes/ReReloop.cpp +++ b/src/passes/ReReloop.cpp @@ -345,6 +345,18 @@ struct ReReloop final : public Pass { auto temp = builder->addVar(function, i32); CFG::RelooperBuilder builder(*module, temp); function->body = relooper.Render(builder); + // if the function has a result, and the relooper emitted + // something that seems like it flows out without a value + // (but that path is never reached; it just has a br to it + // because of the relooper's boilerplate switch-handling + // code, for example, which could be optimized out later + // but isn't yet), then make sure it has a proper type + if (function->result != none && function->body->type == none) { + function->body = builder.makeSequence( + function->body, + builder.makeUnreachable() + ); + } } // TODO: should this be in the relooper itself? ReFinalize().walk(function->body); diff --git a/test/passes/flatten_rereloop.txt b/test/passes/flatten_rereloop.txt index ba5b6c67a..587124191 100644 --- a/test/passes/flatten_rereloop.txt +++ b/test/passes/flatten_rereloop.txt @@ -43,3 +43,85 @@ ) ) ) +(module + (type $0 (func (result i32))) + (memory $0 0) + (func $0 (; 0 ;) (type $0) (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block + (block + ) + (block $switch$1$leave + (block $switch$1$default + (block $switch$1$case$5 + (block $switch$1$case$4 + (br_table $switch$1$case$5 $switch$1$case$4 $switch$1$default + (i32.const 0) + ) + ) + (block + (block + (block + (nop) + (unreachable) + ) + ) + ) + ) + (block + (block + (block + (nop) + (unreachable) + ) + ) + ) + ) + (block + (block + (block + (nop) + ) + (block $switch$6$leave + (block $switch$6$default + (block $switch$6$case$3 + (br_table $switch$6$case$3 $switch$6$default + (i32.const 1) + ) + ) + (block + (block + (block + (nop) + (unreachable) + ) + ) + ) + ) + (block + (block + (block + (nop) + (set_local $0 + (i32.const 2) + ) + (set_local $1 + (get_local $0) + ) + (return + (get_local $1) + ) + ) + ) + ) + ) + ) + ) + (br $switch$1$leave) + ) + ) + (unreachable) + ) +) diff --git a/test/passes/flatten_rereloop.wast b/test/passes/flatten_rereloop.wast index b575f9c55..2584b5146 100644 --- a/test/passes/flatten_rereloop.wast +++ b/test/passes/flatten_rereloop.wast @@ -9,4 +9,28 @@ (f64.const -nan:0xfffffd63e4e5a) ) ) +(module + (func $0 (result i32) + (block $label$8 + (block $label$9 + (block $label$16 + (block $label$18 + (block $label$19 + (br_table $label$18 $label$16 $label$19 + (i32.const 0) + ) + ) + (br_table $label$9 $label$8 + (i32.const 1) + ) + ) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (i32.const 2) + ) +) diff --git a/test/passes/rereloop.txt b/test/passes/rereloop.txt index b5750b16c..52f088594 100644 --- a/test/passes/rereloop.txt +++ b/test/passes/rereloop.txt @@ -713,20 +713,31 @@ (func $switcher-to-nowhere (; 13 ;) (type $2) (param $0 i32) (result i32) (local $1 i32) (block - ) - (block $switch$1$leave - (block $switch$1$default - (block $switch$1$case$3 - (block $switch$1$case$4 - (br_table $switch$1$case$4 $switch$1$case$3 $switch$1$default - (get_local $0) + (block + ) + (block $switch$1$leave + (block $switch$1$default + (block $switch$1$case$3 + (block $switch$1$case$4 + (br_table $switch$1$case$4 $switch$1$case$3 $switch$1$default + (get_local $0) + ) + ) + (block + (block + (block + (return + (i32.const 1) + ) + ) + ) ) ) (block (block (block (return - (i32.const 1) + (i32.const 2) ) ) ) @@ -736,22 +747,14 @@ (block (block (return - (i32.const 2) + (i32.const 3) ) ) ) ) ) - (block - (block - (block - (return - (i32.const 3) - ) - ) - ) - ) ) + (unreachable) ) ) (module |