Binaryen: Fuzz failures after #2702

Created on 22 Apr 2020  路  11Comments  路  Source: WebAssembly/binaryen

$ bin/wasm-opt a.wasm -Oz -all
expected (v128, anyref), seeing v128 from
0x557a7c7f08e8
wasm-opt: src/wasm-interpreter.h:258: wasm::Flow wasm::ExpressionRunner<SubType>::visit(wasm::Expression*) [with SubType = wasm::PrecomputingExpressionRunner]: Assertion `Type::isSubType(type, curr->type)' failed.
Aborted

a.wasm.gz

Bisected this to have started with #2702

cc @dcodeIO

Most helpful comment

Postmortem: dcode should not use std::move since he doesn't understand it. Upcoming fix is to remove any std::moves introduced by dcode.

All 11 comments

Have a feeling that this has something to do with the runner being a bit more forgiving now, going to look into this!

So far found that

$> wasm-opt --all-features --precompute-propagte a.wasm

triggers the problem. Now throwing it at wasm-reduce, while hoping that I'm doing this right :)

Reduced: a.reduced.wasm.gz

After fixing WASM_INTERPRETER_DEBUG and activating it I'm seeing:

1:  visit Unreachable : 0x7fffc1242a90
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1242b40
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1242c60
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1242d80
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1242dd8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243000
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243058
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc12432d8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243410
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc12434d8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243530
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc12435f8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243730
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243788
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243838
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243890
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc12438e8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243ad8
1:  exit Unreachable
1:  visit Unreachable : 0x7fffc1243bf8
1:  exit Unreachable
1:  visit GlobalGet : 0x7fffc1244278
1:  name (global$2)
1:  exit GlobalGet
1:  visit Unreachable : 0x7fffc1244330
1:  exit Unreachable
1:  visit Block : 0x7fffc12444b0
2:   visit RefNull : 0x7fffc12444e8
2:   exit RefNull
1:  exit Block
1:  visit Unreachable : 0x7fffc1244600
1:  exit Unreachable
1:  visit Block : 0x7fffc12446c8
2:   visit Drop : 0x7fffc1245680
3:    visit Block : 0x7fffc1244700
4:     visit Drop : 0x7fffc1245640
5:      visit Block : 0x7fffc1244738
6:       visit Drop : 0x7fffc12455f0
7:        visit Block : 0x7fffc1244770
8:         visit Drop : 0x7fffc12455b0
9:          visit Block : 0x7fffc12447a8
10:           visit Drop : 0x7fffc1245560
11:            visit Block : 0x7fffc12447e0
12:             visit Drop : 0x7fffc1245520
13:              visit Block : 0x7fffc1244818
14:               visit Drop : 0x7fffc12454d0
15:                visit Block : 0x7fffc1244850
16:                 visit Drop : 0x7fffc1245400
17:                  visit Block : 0x7fffc1244888
18:                   visit Drop : 0x7fffc12453b0
19:                    visit Block : 0x7fffc12448c0
20:                     visit Drop : 0x7fffc1245378
21:                      visit Block : 0x7fffc12448f8
22:                       visit Drop : 0x7fffc1245338
23:                        visit Block : 0x7fffc1244930
24:                         visit Drop : 0x7fffc12452e8
25:                          visit Block : 0x7fffc1244968
26:                           visit Drop : 0x7fffc12452a8
27:                            visit Block : 0x7fffc12449a0
28:                             visit Drop : 0x7fffc1245258
29:                              visit Block : 0x7fffc12449d8
30:                               visit Drop : 0x7fffc1245218
31:                                visit Block : 0x7fffc1244a10
32:                                 visit Drop : 0x7fffc12451c8
33:                                  visit Block : 0x7fffc1244a48
34:                                   visit Drop : 0x7fffc1245190
35:                                    visit Block : 0x7fffc1244a80
36:                                     visit Drop : 0x7fffc1245150
37:                                      visit Block : 0x7fffc1244ab8
38:                                       visit Drop : 0x7fffc1245100
39:                                        visit Block : 0x7fffc1244af0
40:                                         visit Drop : 0x7fffc12450c0
41:                                          visit Block : 0x7fffc1244b28
42:                                           visit Drop : 0x7fffc1245070
43:                                            visit Block : 0x7fffc1244b60
44:                                             visit LocalSet : 0x7fffc1244c88
44:                                             eval curr->index (163)
45:                                              visit Block : 0x7fffc1244b98
46:                                               visit tuple.make : 0x7fffc1244c30
47:                                                visit generateArguments
48:                                                 visit Const : 0x7fffc1244bd0
48:                                                 eval curr->value (i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
48:                                                 exit Const
47:                                                eval flow.values (i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
48:                                                 visit RefNull : 0x7fffc1244bf8
48:                                                 exit RefNull
47:                                                eval flow.values (nullref)
48:                                                 visit Const : 0x7fffc1244c08
48:                                                 eval curr->value (0)
48:                                                 exit Const
47:                                                eval flow.values (0)
47:                                                exit generateArguments
46:                                               exit tuple.make
45:                                              exit Block
44:                                             exit LocalSet
44:                                             visit Drop : 0x7fffc1244e30
45:                                              visit Block : 0x7fffc1244e48
46:                                               visit LocalSet : 0x7fffc1244e90
46:                                               eval curr->index (165)
47:                                                visit tuple.extract : 0x7fffc1244cc0
48:                                                 visit LocalGet : 0x7fffc1244ca8
48:                                                 eval curr->index (163)
48:                                                 exit LocalGet
47:                                                exit tuple.extract
46:                                               exit LocalSet
46:                                               visit Drop : 0x7fffc1244d68
47:                                                visit Block : 0x7fffc1244d80
48:                                                 visit LocalSet : 0x7fffc1244dc8
48:                                                 eval curr->index (164)
49:                                                  visit tuple.extract : 0x7fffc1244cf8
50:                                                   visit LocalGet : 0x7fffc1244ce0
50:                                                   eval curr->index (163)
50:                                                   exit LocalGet
expected (v128, anyref, i64), seeing v128 from
0x7fffece0bce0
wasm-opt: /path/to/wasm-interpreter.h:258: wasm::Flow wasm::ExpressionRunner<SubType>::visit(wasm::Expression*) [with SubType = wasm::PrecomputingExpressionRunner]: Assertion `Type::isSubType(type, curr->type)' failed.
Aborted (core dumped)

Try adding BINARYEN_CORES=1 to avoid all the messy thread interleaving stuff.

Thanks, updated the output :)

Is this after running wasm-reduce? I'm surprised it wouldn't have reduced the program more. Otherwise my next step would be to dive in with gdb:

$ gdb --args <bad wasm-opt invocation>
... blah blah blah GDB stuff ...
(gdb) run
... program runs until it crashes ...
(gdb) backtrace
... helpful backtrace printed with frame numbers ...
(gdb) frame <n>
... now we're at the interesting frame. We can go up and down frames with `up` and `down`
(gdb) tui enable
... now we have a nice text UI in the terminal and we can see where in the code we are ...
(gdb) print <some interesting C++ expression>
... now we can examine variables and their contents and figure out the issue ...

Side note: I'm not sure when WASM_INTERPRETER_DEBUG has ever been useful. Maybe can just get rid of it?

Yeah, that's after wasm-reduce. Perhaps I did something wrong? Invocation was

wasm-reduce --command 'wasm-opt --all-features --precompute-propagate testing.wasm' --test testing.wasm --working working.wasm a.wasm

Going to look into using gdb, hope this doesn't have unforeseen consequences in WSL :)

What I can tell so far is that there's a

(local.get $163)

returning a Flow with a single (v128) value where values should be (v128, anyref, i64) after being set from a tuple.make.

The corresponding tuple.make of the local.set is

(tuple.make
 (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
 (ref.null)
 (i64.const 0)
)

running through a block, stored to the local, then stuff happens and the respective local.get returns something wrong.

wasm-reduce doesn't work well on testcases like this, because the multivalue stuff increases the size every time you save. So it think it's failing to reduce and stops early. I thought I opened an issue for that but looks like not?

You can reduce with --text so it's on the wat format which avoids most of that.

Oh, appears the cause is the std::move in visitLocalGet, corrupting the value down the road.

Postmortem: dcode should not use std::move since he doesn't understand it. Upcoming fix is to remove any std::moves introduced by dcode.

Was this page helpful?
0 / 5 - 0 ratings