summaryrefslogtreecommitdiff
path: root/src/tools/fuzzing
Commit message (Collapse)AuthorAgeFilesLines
* [NFC] Make MemoryOrder parameters non-optional (#7171)Thomas Lively2024-12-211-2/+3
| | | | | | Update Builder and IRBuilder makeStructGet and makeStructSet functions to require the memory order to be explicitly supplied. This is slightly more verbose, but will reduce the chances that we forget to properly consider synchronization when implementing new features in the future.
* Fuzz JSPI (#7148)Alon Zakai2024-12-161-0/+29
| | | | | | | | | | * Add a new "sleep" fuzzer import, that does a sleep for some ms. * Add JSPI support in fuzz_shell.js. This is in the form of commented-out async/await keywords - commented out so that normal fuzzing is not impacted. When we want to fuzz JSPI, we uncomment them. We also apply the JSPI operations of marking imports and exports as suspending/promising. JSPI fuzzing is added to both fuzz_opt.py and ClusterFuzz's run.py.
* Fuzzer: Add call-ref, call-ref-catch imports (#7137)Alon Zakai2024-12-091-31/+91
| | | | | | | | | | | | | | | Similar to call-export*, these imports call a wasm function from outside the module. The difference is that we send a function reference for them to call (rather than an export index). This gives more coverage, first by sending a ref from wasm to JS, and also since we will now try to call anything that is sent. Exports, in comparison, are filtered by the fuzzer to things that JS can handle, so this may lead to more traps, but maybe also some new situations. This also leads to adding more logic to execution-results.h to model JS trapping properly. fuzz_shell.js is refactored to allow sharing code between call-export* and call-ref*.
* [NFC] Send the closed-world flag to TranslateToFuzzReader (#7136)Alon Zakai2024-12-051-6/+13
| | | | | | | | | | | This sends --closed-world to wasm-opt from the fuzzer, when we use that flag (before we just used it on optimizations, but not fuzz generation). And TranslateToFuzzReader now stores a boolean about whether we are in closed- world mode or not. This has no effect so far, and is a refactoring for a later PR, where we must generate code differently based on whether we are in closed-world mode or not.
* Make validation of stale types stricter (#7097)Thomas Lively2024-11-211-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We previously allowed valid expressions to have stale types as long as those stale types were supertypes of the most precise possible types for the expressions. Allowing stale types like this could mask bugs where we failed to propagate precise type information, though. Make validation stricter by requiring all expressions except for control flow structures to have the most precise possible types. Control flow structures are exempt because many passes that can refine types wrap the refined expressions in blocks with the old type to avoid the need for refinalization. This pattern would be broken and we would need to refinalize more frequently without this exception for control flow structures. Now that all non-control flow expressions must have precise types, remove functionality relating to building select instructions with non-precise types. Since finalization of selects now always calculates a LUB rather than using a provided type, remove the type parameter from BinaryenSelect in the C and JS APIs. Now that stale types are no longer valid, fix a bug in TypeSSA where it failed to refinalize module-level code. This bug previously would not have caused problems on its own, but the stale types could cause problems for later runs of Unsubtyping. Now the stale types would cause TypeSSA output to fail validation. Also fix a bug where Builder::replaceWithIdenticalType was in fact replacing with refined types. Fixes #7087.
* Fuzzer: Legalize and prune the JS interface in pickPasses (#7092)Alon Zakai2024-11-201-0/+7
| | | | Also add a test that the ClusterFuzz run.py does not warn, which was helpful when debugging this.
* Improve fuzzing of both closed and open world styles of modules (#7090)Alon Zakai2024-11-191-21/+16
| | | | | | | | | | Before, we would simply not export a function that had an e.g. anyref param. As a result, the modules were effectively "closed", which was good for testing full closed-world mode, but not for testing degrees of open world. To improve that, this PR allows the fuzzer to export such functions, and an "enclose world" pass is added that "closes" the wasm (makes it more compatible with closed-world) that is run 50% of the time, giving us coverage of both styles.
* Fuzzing: ClusterFuzz integration (#7079)Alon Zakai2024-11-191-12/+121
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The main addition here is a bundle_clusterfuzz.py script which will package up the exact files that should be uploaded to ClusterFuzz. It also documents the process and bundling and testing. You can do bundle.py OUTPUT_FILE.tgz That bundles wasm-opt from ./bin., which is enough for local testing. For actually uploading to ClusterFuzz, we need a portable build, and @dschuff had the idea to reuse the emsdk build, which works nicely. Doing bundle.py OUTPUT_FILE.tgz --build-dir=/path/to/emsdk/upstream/ will bundle wasm-opt (+libs) from the emsdk. I verified that those builds work on ClusterFuzz. I added several forms of testing here. First, our main fuzzer fuzz_opt.py now has a ClusterFuzz testcase handler, which simulates a ClusterFuzz environment. Second, there are smoke tests that run in the unit test suite, and can also be run separately: python -m unittest test/unit/test_cluster_fuzz.py Those unit tests can also run on a given bundle, e.g. one created from an emsdk build, for testing right before upload: BINARYEN_CLUSTER_FUZZ_BUNDLE=/path/to/bundle.tgz python -m unittest test/unit/test_cluster_fuzz.py A third piece of testing is to add a --fuzz-passes test. That is a mode for -ttf (translate random data into a valid wasm fuzz testcase) that uses random data to pick and run a set of passes, to further shape the wasm. (--fuzz-passes had no previous testing, and this PR fixes it and tidies it up a little, adding some newer passes too). Otherwise this PR includes the key run.py script that is bundled and then executed by ClusterFuzz, basically a python script that runs wasm-opt -ttf [..] to generate testcases, sets up their JS, and emits them. fuzz_shell.js, which is the JS to execute testcases, will now check if it is provided binary data of a wasm file. If so, it does not read a wasm file from argv[1]. (This is needed because ClusterFuzz expects a single file for the testcase, so we make a JS file with bundled wasm inside it.)
* [wasm64] Fuzzer: Fix type of unimported offsets (#7071)Alon Zakai2024-11-111-2/+2
| | | | | | When the fuzzer sees an imported segment, it makes it non-imported (because imported ones would trap when we tried to run them: we don't have the normal runtime they expect). We had hardcoded i32 offets there, which need to be generalized.
* [EH] Fuzz calls from JS by calling wasm exports, sometimes catching (#7067)Alon Zakai2024-11-081-1/+83
| | | | | | | | | | | | | | | | This adds two new imports to fuzzer modules: * call-export, which gets an export index and calls it. * call-export-catch, which does the call in a try-catch, swallowing any error, and returning 1 if it saw an error. The former gives us calls back into the wasm, possibly making various trips between wasm and JS in interesting ways. The latter adds a try-catch which helps fuzz wasm EH. We do these calls using a wasm export index, i.e., the index in the list of exports. This is simple, but it does have the downside that it makes executing the wasm sensitive to changes in exports (e.g. wasm-merge adds more), which requires some handling in the fuzzer.
* Rename indexType -> addressType. NFC (#7060)Sam Clegg2024-11-071-15/+15
| | | See https://github.com/WebAssembly/memory64/pull/92
* [wasm64] Fix copying of 64-bit tables, and fuzz them (#7065)Alon Zakai2024-11-071-2/+20
| | | | `ModuleUtils::copyTable` was not copying the `indexType` property.
* [wasm64] Fuzz wasm64 memories (#7064)Alon Zakai2024-11-071-7/+27
| | | | | | | * Remove the code that prevented fuzzing wasm64 test files. * Ignore a run that hits the V8 implementation limit on memory size. * Disable wasm64 fuzzing in wasm2js (like almost all post-MVP features). * Add fuzzer logic to emit a 64-bit memory sometimes. * Fix various places in the fuzzer that assumed 32-bit indexes
* Fuzz the Table from JS (#7042)Alon Zakai2024-10-311-0/+70
| | | | | Continues the work from #7027 which added throwing from JS, this adds table get/set operations from JS, to further increase our coverage of Wasm/JS interactions (the table can be used from both sides).
* [EH] Fuzz throws from JS (#7027)Alon Zakai2024-10-231-19/+47
| | | | | | | | | | | We already generated (throw ..) instructions in wasm, but it makes sense to model throws from outside as well, as they cross the module boundary. This adds a new fuzzer import to the generated modules, "throw", that just does a throw from JS etc. Also be more precise about handling fuzzing-support imports in fuzz-exec: we now check that logging functions start with "log*" and error otherwise (this check is now needed given we have "throw", which is not logging). Also fix a minor issue with name conflicts for logging functions by using getValidFunctionName for them, both for logging and for throw.
* [Wasm GC] Fuzz BrOn (#7006)Alon Zakai2024-10-161-6/+118
|
* Fuzzer: Generate TryTables (#6987)Alon Zakai2024-10-071-0/+68
| | | | Also make Try/TryTables with type none, and not just concrete types as before.
* [FP16] Implement conversion operations. (#6974)Brendan Dahl2024-09-261-1/+5
| | | | | | | | | | Note: FP16 is a little different from F32/F64 since it can't represent the full 2^16 integer range. 65504 is the max whole integer. This leads to some slightly strange behavior when converting integers greater than 65504 since they become infinity. Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Implement unary operations. (#6867)Brendan Dahl2024-08-271-25/+36
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Add a feature flag for FP16. (#6864)Brendan Dahl2024-08-221-117/+130
| | | Ensure the "fp16" feature is enabled for FP16 instructions.
* [FP16] Implement arithmetic operations. (#6855)Brendan Dahl2024-08-211-0/+6
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [NFC] Use HeapType::getKind more broadly (#6846)Thomas Lively2024-08-192-109/+142
| | | | | | | | Replace code that checked `isStruct()`, `isArray()`, etc. in sequence with uses of `HeapType::getKind()` and switch statements. This will make it easier to find the code that needs updating if/when we add new heap type kinds in the future. It also makes it much easier to find code that already needs updating to handle continuation types by grepping for "TODO: cont".
* [FP16] Implement relation operations. (#6825)Brendan Dahl2024-08-091-0/+7
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* [FP16] Implement lane access instructions. (#6821)Brendan Dahl2024-08-081-0/+1
| | | | Specified at https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
* Restore isString type methods (#6815)Thomas Lively2024-08-061-2/+1
| | | | | | | | | PR ##6803 proposed removing Type::isString and HeapType::isString in favor of more explicit, verbose callsites. There was no consensus to make this change, but it was accidentally committed as part of #6804. Revert the accidental change, except for the useful, noncontroversial parts, such as fixing the `isString` implementation and a few other locations to correctly handle shared types.
* Fix sharedness bug in inhabitable type fuzzer (#6807)Thomas Lively2024-08-061-1/+2
| | | | | | The code for collecting inhabitable types incorrectly considered shared, non-nullable externrefs to be inhabitable, which disagreed with the code for rewriting types to be inhabitable, which was correct, causing the type fuzzer to report an error.
* [NFC] Add HeapType::getKind returning a new HeapTypeKind enum (#6804)Thomas Lively2024-08-061-1/+2
| | | | | | | | | | | | | | | | | The HeapType API has functions like `isBasic()`, `isStruct()`, `isSignature()`, etc. to test the classification of a heap type. Many users have to call these functions in sequence and handle all or most of the possible classifications. When we add a new kind of heap type, finding and updating all these sites is a manual and error-prone process. To make adding new heap type kinds easier, introduce a new API that returns an enum classifying the heap type. The enum can be used in switch statements and the compiler's exhaustiveness checker will flag use sites that need to be updated when we add a new kind of heap type. This commit uses the new enum internally in the type system, but follow-on commits will add new uses and convert uses of the existing APIs to use `getKind` instead.
* [NFC] Add HeapType::isMaybeShared(BasicHeapType) utility (#6773)Thomas Lively2024-07-181-2/+1
| | | | | | | | | This abbreviates a common pattern where we first had to check whether a heap type was basic, then if it was, get its unshared version and compare it to some expected BasicHeapType. Suggested in https://github.com/WebAssembly/binaryen/pull/6771#discussion_r1683005495.
* [threads] Update the fuzzer for shared types (#6771)Thomas Lively2024-07-182-54/+90
| | | | | | | | Update the fuzzer to both handle shared types in initial contents and create and use new shared types without crashing or producing invalid modules. Since V8 does not have a complete implementation of shared-everything-threads yet, disable fuzzing V8 when shared-everything is enabled. To avoid losing too much coverage of V8, disable shared-everything in the fuzzer more frequently than other features.
* Simplify fuzzer generation of function references (#6745)Thomas Lively2024-07-151-17/+11
| | | | | | | | | | | | When creating a reference to `func`, fix the probability of choosing to continue on to choose some function other than the last one rather than making it depend on the number of functions. Then, do not eagerly pick from the rest of the candidate functions. Instead, fall through to the more general logic that will already pick a random candidate function. Also move the logic for coming up with a concrete signature down to where it is needed. These simplifications will make it easier to update the code to handle shared types.
* [threads] Fuzz shared types in type fuzzer (#6704)Thomas Lively2024-06-262-99/+133
| | | | | | | | | | | | | | Give the type fuzzer the ability to generate shared heap types when the shared-everything feature is enabled. It correctly ensures that shared structs and arrays cannot reference unshared heap types, but that unshared heap types can reference any heap type. Update the main fuzzer so that for the time being it never uses the shared-everything feature when generating additional heap types, so it never generates shared types. We can lift this restriction once the main fuzzer has been updated to properly handle shared types. As a drive-by, fix some logic for subtracting feature sets from each other that is used in this commit.
* [threads] Shared basic heap types (#6667)Thomas Lively2024-06-192-4/+8
| | | | | | | | | | | Implement binary and text parsing and printing of shared basic heap types and incorporate them into the type hierarchy. To avoid the massive amount of code duplication that would be necessary if we were to add separate enum variants for each of the shared basic heap types, use bit 0 to indicate whether the type is shared and replace `getBasic()` with `getBasic(Unshared)`, which clears that bit. Update all the use sites to record whether the original type was shared and produce shared or unshared output without code duplication.
* Fix fuzzer generation of a DataSegment + add validation that would have ↵Alon Zakai2024-05-231-3/+4
| | | | | | | | | | caught it (#6626) The DataSegment was manually added to .dataSegments, but we need to add it using addDataSegment so the maps are updated and getDataSegment(name) works. Also add validation that would have caught this earlier: check that each item in the item lists can be fetched by name.
* Fuzzer: Better fuzzing of globals (#6611)Alon Zakai2024-05-212-33/+53
| | | | | | | | | | | | | With this PR we generate global.gets in globals, which we did not do before. We do that by replacing makeConst (the only thing we did before, for the contents of globals) with makeTrivial, and add code to makeTrivial to sometimes make a global.get. When no suitable global exists, makeGlobalGet will emit a constant, so there is no danger in trying. Also raise the number of globals a little. Also explicitly note the current limitation of requiring all tuple globals to contain tuple.make and nothing else, including not global.get, and avoid adding such invalid global.gets in tuple globals in the fuzzer.
* [Strings] Remove operations not included in imported strings (#6589)Thomas Lively2024-05-151-3/+2
| | | | | | The stringref proposal has been superseded by the imported JS strings proposal, but the former has many more operations than the latter. To reduce complexity, remove all operations that are part of stringref but not part of imported strings.
* [Strings] Remove stringview types and instructions (#6579)Thomas Lively2024-05-152-44/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The stringview types from the stringref proposal have three irregularities that break common invariants and require pervasive special casing to handle properly: they are supertypes of `none` but not subtypes of `any`, they cannot be the targets of casts, and they cannot be used to construct nullable references. At the same time, the stringref proposal has been superseded by the imported strings proposal, which does not have these irregularities. The cost of maintaing and improving our support for stringview types is no longer worth the benefit of supporting them. Simplify the code base by entirely removing the stringview types and related instructions that do not have analogues in the imported strings proposal and do not make sense in the absense of stringviews. Three remaining instructions, `stringview_wtf16.get_codeunit`, `stringview_wtf16.slice`, and `stringview_wtf16.length` take stringview operands in the stringref proposal but cannot be removed because they lower to operations from the imported strings proposal. These instructions are changed to take stringref operands in Binaryen IR, and to allow a graceful upgrade path for users of these instructions, the text and binary parsers still accept but ignore `string.as_wtf16`, which is the instruction used to convert stringrefs to stringviews. The binary writer emits code sequences that use scratch locals and `string.as_wtf16` to keep the output valid. Future PRs will further align binaryen with the imported strings proposal instead of the stringref proposal, for example by making `string` a subtype of `extern` instead of a subtype of `any` and by removing additional instructions that do not have analogues in the imported strings proposal.
* Fuzzer: Stop emitting nullable stringviews (#6574)Alon Zakai2024-05-081-5/+17
| | | | | | | | | | | | | As of https://chromium-review.googlesource.com/c/v8/v8/+/5471674 V8 requires stringviews to be non-nullable. It might be possible to make that change in our IR, or to remove views entirely, but for now this PR makes the fuzzer stop emitting nullable stringviews as a workaround to allow us to fuzz current V8. There are still rare corner cases where this pattern is emitted, that we have not tracked down, and so this also makes the fuzzer ignore the error for now.
* [Strings] Work around ref.cast not working on string views, and add fuzzing ↵Alon Zakai2024-04-291-4/+31
| | | | | | | | | | | | | (#6549) As suggested in #6434 (comment) , lower ref.cast of string views to ref.as_non_null in binary writing. It is a simple hack that avoids the problem of V8 not allowing them to be cast. Add fuzzing support for the last three core string operations, after which that problem becomes very frequent. Also add yet another makeTrappingRefUse that was missing in that fuzzer code.
* [Strings] Fix effects of string.compare and add fuzzing (#6547)Alon Zakai2024-04-251-10/+24
| | | | | | | | We added string.compare late in the spec process, and forgot to add effects for it. Unlike string.eq, it can trap. Also use makeTrappingRefUse in recent fuzzer string generation places that I forgot, which should reduce the amount of traps in fuzzer output.
* [Strings] Fuzz string.encode (#6539)Alon Zakai2024-04-251-14/+50
| | | | | | | A little trickier than the others due to the risk of trapping, which this handles like the other array operations. Also stop using immutable i16 arrays for string operations - only mutable ones work atm.
* Fuzzer: Update the typeLocals data structure before mutation (#6537)Alon Zakai2024-04-241-2/+12
| | | | | Rather than compute the map of type to locals of that type once, at the start, also update it when relevant, as we can add more locals in some cases. This allows us to local.get from those late-added locals too.
* [Strings] Fuzzer: Emit StringConcat (#6532)Alon Zakai2024-04-241-66/+86
| | | Also refactor the code a little to make it easier to add this (mostly whitespace).
* [Strings] Add the string heaptype to core fuzzer places (#6527)Alon Zakai2024-04-231-20/+23
| | | | | | | With this we emit strings spontaneously (as opposed to just getting them from initial contents). The relevant -ttf test has been tweaked slightly to show the impact of this change: now there are some string.new/const in the output.
* [Strings] Fuzz and interpret all relevant StringNew methods (#6526)Alon Zakai2024-04-231-41/+80
| | | | This adds fuzzing for string.new_wtf16_array and string.from_code_point. The latter was also missing interpreter support, which this adds.
* Fuzzer: Randomly pick which functions to use in RefFunc (#6503)Alon Zakai2024-04-151-10/+12
| | | | | | | Previously we chose the first with a proper type, and now we start to scan from a random index, giving later functions a chance too, so we should be emitting a greater variety of ref.func targets. Also remove some obsolete fuzzer TODOs.
* Fuzzer: Emit signed Struct/ArrayGet operations (#6486)Alon Zakai2024-04-111-5/+12
|
* Typed continuations: nocont and cont basic heap types (#6468)Frank Emrich2024-04-042-0/+13
| | | | | | | | This PR is part of a series that adds basic support for the typed continuations/wasmfx proposal. This particular PR adds cont and nocont as top and bottom types for continuation types, completely analogous to func and nofunc for function types (also: exn and noexn).
* Fuzzer HeapType generator: Do not use string types if not allowed (#6447)Alon Zakai2024-03-271-1/+1
|
* Fuzzer: Work around the lack of wtf8/iter support (#6445)Alon Zakai2024-03-271-5/+6
| | | | We only have interpreter support for wtf16, so we should not emit operations on the other types, as the interpreter will error.
* Fix stringview subtyping (#6440)Thomas Lively2024-03-261-1/+8
| | | | | | The stringview types (`stringview_wtf8`, `stringview_wtf16`, and `stringview_iter`) are not subtypes of `any` even though they are supertypes of `none`. This breaks the type system invariant that types share a bottom type iff they share a top type, but we can work around that.