diff options
author | Alon Zakai <azakai@google.com> | 2021-03-22 16:13:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-22 16:13:33 -0700 |
commit | 8dddd9f3a3060d831af48387165703e1d8efcc63 (patch) | |
tree | 884a4f848abaae13091be910cdf6de1a100951c0 /test | |
parent | 5c17d353ce24dffabf05d7fd2bf9d20a3618962f (diff) | |
download | binaryen-8dddd9f3a3060d831af48387165703e1d8efcc63.tar.gz binaryen-8dddd9f3a3060d831af48387165703e1d8efcc63.tar.bz2 binaryen-8dddd9f3a3060d831af48387165703e1d8efcc63.zip |
Fix a fuzz regression from #3669 (#3715)
I'm not entirely sure how LUB removal made this noticeable, as it seems
to be a pre-existing bug. However, somehow before #3669 it was not
noticable - perhaps the finalize code worked around it.
The bug is that RemoveUnusedBrs was moving code around and
finalizing the parent before the child. The correct pattern is always to
work from the children outwards, as otherwise the parent is trying to
finalize itself based on non-finalized children.
The fix is to just not finalize in the stealSlice method. The caller can
do it after finishing any other work it has. As part of this refactoring,
move stealSlice into the single pass that uses it; aside from that being
more orderly, this method is really not a general-purpose tool, it is
quite specific to what RemoveUnusedBrs does, and it might easily
be used incorrectly elsewhere.
Diffstat (limited to 'test')
-rw-r--r-- | test/passes/remove-unused-brs_all-features.txt | 18 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_all-features.wast | 21 |
2 files changed, 39 insertions, 0 deletions
diff --git a/test/passes/remove-unused-brs_all-features.txt b/test/passes/remove-unused-brs_all-features.txt index 4bf1cfb33..3365ebb75 100644 --- a/test/passes/remove-unused-brs_all-features.txt +++ b/test/passes/remove-unused-brs_all-features.txt @@ -1,6 +1,7 @@ (module (type $struct (struct (field (ref null $vector)))) (type $vector (array (mut i32))) + (type $none_=>_f64 (func (result f64))) (type $none_=>_ref?|$struct| (func (result (ref null $struct)))) (func $foo (result (ref null $struct)) (if (result (ref null $struct)) @@ -15,4 +16,21 @@ (ref.null $struct) ) ) + (func $test-prefinalize (result f64) + (loop $loop (result f64) + (if (result f64) + (i32.const 1) + (f64.const 0) + (block $block (result f64) + (nop) + (br_if $loop + (i32.eqz + (i32.const 0) + ) + ) + (unreachable) + ) + ) + ) + ) ) diff --git a/test/passes/remove-unused-brs_all-features.wast b/test/passes/remove-unused-brs_all-features.wast index 4d1a337c6..3703bb9f2 100644 --- a/test/passes/remove-unused-brs_all-features.wast +++ b/test/passes/remove-unused-brs_all-features.wast @@ -16,4 +16,25 @@ (ref.null $struct) ) ) + (func $test-prefinalize (result f64) + (loop $loop (result f64) + (block $block (result f64) + (drop + (br_if $block + (f64.const 0) + (i32.const 1) + ) + ) + (if + (i32.const 0) + (unreachable) + ) + ;; this will be moved from $block into the if right before it. we must be + ;; careful to properly finalize() things, as if we finalize the block too + ;; early - before the if - then the block ends in a none type, which is + ;; invalid. + (br $loop) + ) + ) + ) ) |