|
| 1 | + |
| 2 | + |
| 3 | +## Run fuzzer |
| 4 | + |
| 5 | +Run Fizzy vs WABT verification fuzzer, currently in `fuzzing` branch. |
| 6 | +Start with small inputs. |
| 7 | + |
| 8 | +```shell script |
| 9 | +bin/fizzy-fuzz-parser corpus -max_len=13 |
| 10 | +``` |
| 11 | + |
| 12 | +In case it finds a failure you will see output like |
| 13 | +```text |
| 14 | +INFO: Seed: 770491456 |
| 15 | +INFO: Loaded 1 modules (64068 inline 8-bit counters): 64068 [0xb8dc90, 0xb9d6d4), |
| 16 | +INFO: Loaded 1 PC tables (64068 PCs): 64068 [0xb9d6d8,0xc97b18), |
| 17 | +INFO: 10986 files found in corpus |
| 18 | +INFO: seed corpus: files: 10986 min: 1b max: 27419b total: 740862b rss: 40Mb |
| 19 | +#11160 INITED cov: 7782 ft: 9644 corp: 227/2677b exec/s: 0 rss: 186Mb |
| 20 | +#65536 pulse cov: 7782 ft: 9644 corp: 227/2677b lim: 13 exec/s: 32768 rss: 215Mb |
| 21 | +#131072 pulse cov: 7782 ft: 9644 corp: 227/2677b lim: 13 exec/s: 32768 rss: 248Mb |
| 22 | +#262144 pulse cov: 7782 ft: 9644 corp: 227/2677b lim: 13 exec/s: 32768 rss: 314Mb |
| 23 | + MALFORMED: invalid limits 4 |
| 24 | +/home/chfast/Projects/wasmx/fizzy/test/fuzzer/parser_fuzzer.cpp:47:9: runtime error: execution reached an unreachable program point |
| 25 | +SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/chfast/Projects/wasmx/fizzy/test/fuzzer/parser_fuzzer.cpp:47:9 in |
| 26 | +MS: 1 ChangeBit-; base unit: 846f4928f92649789961543e93544b4c2ed6fc44 |
| 27 | +0x0,0x61,0x73,0x6d,0x1,0x0,0x0,0x0,0x5,0x3,0x1,0x4,0x2b, |
| 28 | +\x00asm\x01\x00\x00\x00\x05\x03\x01\x04+ |
| 29 | +artifact_prefix='./'; Test unit written to ./crash-016934f781c41276bfacda9a90385cef85a88d5f |
| 30 | +Base64: AGFzbQEAAAAFAwEEKw== |
| 31 | +``` |
| 32 | + |
| 33 | +In this example Fizzy reported the error `MALFORMED: invalid limits 4` |
| 34 | +while WABT considers the Wasm binary valid. |
| 35 | +The test unit (Wasm binary) is also printed in various forms and saved as |
| 36 | +`crash-016934f781c41276bfacda9a90385cef85a88d5f`. |
| 37 | + |
| 38 | + |
| 39 | +## Check WebAssembly spec interpreter |
| 40 | + |
| 41 | +In case of false negative validation result in WABT it is likely that |
| 42 | +such case is missing in the WAST spec test. |
| 43 | + |
| 44 | +Build the `wasm reference interpreter` following official instructions. |
| 45 | + |
| 46 | +Rename `crash-016934f781c41276bfacda9a90385cef85a88d5f` to `crash.wasm` |
| 47 | +as the interpreter need proper files extension to recognize file type. |
| 48 | + |
| 49 | +```shell script |
| 50 | +./wasm crash.wasm |
| 51 | +``` |
| 52 | + |
| 53 | +Output: |
| 54 | +```text |
| 55 | +crash.wasm:0xb: decoding error: integer too large |
| 56 | +``` |
| 57 | + |
| 58 | +Good news. This is effectively the same error reported as in Fizzy. In Wasm 1.0 `limits` kind |
| 59 | +can be 0 or 1. The the value 4 in the `crash.wasm` is larger than the max 1. |
| 60 | + |
| 61 | + |
| 62 | +## Inspect with WABT tools |
| 63 | + |
| 64 | +You can use `wasm2wat` or `wasm-validate` tools to confirm the bug in WABT. |
| 65 | +Make sure you use the same version as used for fuzzing. |
| 66 | +Disable all extensions except "mutable globals". |
| 67 | + |
| 68 | +In our example, `wasm2wat crash.wasm`: |
| 69 | +```webassembly |
| 70 | +(module |
| 71 | + (memory (;0;) 43 i64)) |
| 72 | +``` |
| 73 | +This indicates that the issue is in the memory section. |
| 74 | + |
| 75 | +Unfortunately, we get different error as the data section also has invalid length. |
| 76 | +Let's fix that. |
| 77 | + |
| 78 | + |
| 79 | +## Prepare WAST test |
| 80 | + |
| 81 | +Dump the test unit (`xxd -p -c1000 crash.wasm`): |
| 82 | + |
| 83 | +```hexdump |
| 84 | +0061736d01000000050301042b |
| 85 | +``` |
| 86 | + |
| 87 | +Here are created WAST tests, placed in `new.wast` file. In the original `crash.wasm` the invalid 4 |
| 88 | +is followed by `2b` byte. We added 2 more variants of the test with byte `00` and without any |
| 89 | +following byte (remember to change the section length if you actually modify the length). |
| 90 | + |
| 91 | +```wast |
| 92 | +(assert_malformed |
| 93 | + (module binary |
| 94 | + "\00asm" "\01\00\00\00" |
| 95 | + "\05\03\01" ;; memory section |
| 96 | + "\04\2b" ;; malformed memory limit 4 |
| 97 | + ) |
| 98 | + "integer too large" |
| 99 | +) |
| 100 | +
|
| 101 | +(assert_malformed |
| 102 | + (module binary |
| 103 | + "\00asm" "\01\00\00\00" |
| 104 | + "\05\03\01" ;; memory section |
| 105 | + "\04\00" ;; malformed memory limit 4 |
| 106 | + ) |
| 107 | + "integer too large" |
| 108 | +) |
| 109 | +
|
| 110 | +(assert_malformed |
| 111 | + (module binary |
| 112 | + "\00asm" "\01\00\00\00" |
| 113 | + "\05\02\01" ;; memory section |
| 114 | + "\04" ;; malformed memory limit 4 |
| 115 | + ) |
| 116 | + "integer too large" |
| 117 | +) |
| 118 | +``` |
| 119 | + |
| 120 | +These tests can be rechecked with WABT. |
| 121 | + |
| 122 | +```shell script |
| 123 | +wast2json new.wast |
| 124 | +wasm-validate new.0.wasm |
| 125 | +wasm-validate new.1.wasm |
| 126 | +wasm-validate new.2.wasm |
| 127 | +``` |
| 128 | + |
| 129 | +The last test case is actually failing in WABT for some other reason, but it can stay as a valid |
| 130 | +spectests addition. |
| 131 | + |
| 132 | +```text |
| 133 | +000000c: error: unable to read u32 leb128: memory initial page count |
| 134 | +``` |
| 135 | + |
| 136 | + |
| 137 | +## Debug & fix WABT |
| 138 | + |
| 139 | +Debug `wasm-validate new.0.wasm` to find out why it passes validation. |
| 140 | +Binary loading code is in `binary-reader.cc`. |
| 141 | + |
| 142 | +The example bug is fixed by https://github.com/WebAssembly/wabt/pull/1547. |
| 143 | + |
| 144 | + |
| 145 | +## Send WAST tests upstream |
0 commit comments