summaryrefslogtreecommitdiff
path: root/src/tools/fuzzing/fuzzing.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [EH] Add exnref type back (#6149)Heejin Ahn2023-12-081-1/+13
| | | | | | | | | | | | | At the Oct hybrid CG meeting, we decided to add back `exnref`, which was removed in 2020: https://github.com/WebAssembly/meetings/blob/main/main/2023/CG-10.md The new version of the proposal reflected in the explainer: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md While adding support for `exnref` in the current codebase which has all GC subtype hierarchies, I noticed we might need `noexn` heap type for the bottom type of `exn`. We don't have it now so I just set it to 0xff for the moment.
* Fuzzer: Better handling of globals from initial content (#6072)Alon Zakai2023-11-011-19/+43
| | | | | | | | | | | | | | | Previously the fuzzer never added gets or sets of globals from initial content. That was an oversight, I'm pretty sure - it's just that the code that sets up the lists from which we pick globals for gets and sets was in another place. That is, any globals in the initial content file were never used in new random code the fuzzer generates (only new globals the fuzzer generated were used there). This PR allows us to use those globals, but also ignores them with some probability, to avoid breaking patterns like "once" globals (that we want to only be used from initial content, at least much of the time). Also simplify the code here: we don't need isInvalidGlobal just to handle the hang limit global, which is already handled by not being added to the lists we pick names from anyhow.
* Fuzzer: Allow non-nullable locals (#6019)Alon Zakai2023-10-181-9/+30
| | | | | | | Remove the code that avoided such locals. To avoid much new trapping, add logic to set a value to such locals if they have accesses that are not dominated by a set already. Also in makeTrivial only rarely emit a local.get of a non-nullable local (prefer a constant).
* Add getGeneralSuperType() that includes basic supers, and use in fuzzer (#6005)Alon Zakai2023-10-171-2/+1
| | | | With this, the fuzzer can replace e.g. an eq expression with a specific struct type, because now it is away that struct types have eq as their ancestor.
* Fuzzer: Move logic for adding a new local on demand to local.get (#6008)Alon Zakai2023-10-171-15/+36
| | | | | | | Previously makeTrappingRefUse would add a local on demand if one was missing for the type, and add a tee for it. This PR moves that logic to makeLocalGet so that we get those benefits any time we want to emit a local.get of a local type that does not exist (including from makeTrappingRefUse which calls makeLocalGet).
* [NFC] Rename getSuperType to getDeclaredSuperType (#6015)Alon Zakai2023-10-171-2/+2
| | | | A later PR will add getSuperType which will mean "get the general super type - either declared, or not".
* Replace i31.new with ref.i31 everywhere (#5931)Thomas Lively2023-09-131-1/+1
| | | | | Replace i31.new with ref.i31 in the printer, tests, and source code. Continue parsing i31.new for the time being to allow a graceful transition. Also update the JS API to reflect the new instruction name.
* Replace I31New with RefI31 everywhere (#5930)Thomas Lively2023-09-131-1/+1
| | | | | | | | Globally replace the source string "I31New" with "RefI31" in preparation for renaming the instruction from "i31.new" to "ref.i31", as implemented in the spec in https://github.com/WebAssembly/gc/pull/422. This would be NFC, except that it also changes the string in the external-facing C APIs. A follow-up PR will make the corresponding behavioral change.
* Remove legacy WasmGC instructions (#5861)Thomas Lively2023-08-091-2/+1
| | | | | Remove old, experimental instructions and type encodings that will not be shipped as part of WasmGC. Updating the encodings and text format to match the final spec is left as future work.
* Fuzzer: Emit more variations of If (#5806)Alon Zakai2023-07-101-2/+24
| | | | | | Before we always created if-elses. Now we also create an If with one arm some of the time, when we can. Also, sometimes make one if arm unreachable, if we have two arms.
* [NFC] Fix the use of "strict" in subtypes.h (#5804)Thomas Lively2023-07-061-1/+1
| | | | | | | | Previously we incorrectly used "strict" to mean the immediate subtypes of a type, when in fact a strict subtype of a type is any subtype excluding the type itself. Rename the incorrect `getStrictSubTypes` to `getImmediateSubTypes`, rename the redundant `getAllStrictSubTypes` to `getStrictSubTypes`, and rename the redundant `getAllSubTypes` to `getSubTypes`. Fixing the capitalization of "SubType" to "Subtype" is left as future work.
* Fuzzing for Try and Throw (#5776)Alon Zakai2023-06-211-3/+71
|
* Fuzzer: Limit ArrayNew sizes most of the time (#5738)Alon Zakai2023-05-221-2/+11
|
* Fuzzer: Use subtype consistently in make() (#5674)Alon Zakai2023-04-191-4/+4
|
* [Wasm GC] Fuzz array.copy and array.fill (#5663)Alon Zakai2023-04-171-4/+84
|
* [Wasm GC] Improve GC operation coverage by using locals more (#5661)Alon Zakai2023-04-171-19/+54
| | | | | | | | | | | | When we emit e.g. a struct.get's reference, this PR makes us prefer a non-nullable value, and even to reuse an existing local if possible. By doing that we reduce the risk of a trap, and also by using locals we end up testing operations on the same data, like this: x = new A(); x.a = .. foo(x.a) In contrast, without this PR each of those x. uses might be new A().
* Remove the --hybrid and --nominal command line options (#5669)Thomas Lively2023-04-141-4/+2
| | | | | After this change, the only type system usable from the tools will be the standard isorecursive type system. The nominal type system is still usable via the API, but it will be removed entirely in a follow-on PR.
* [Wasm GC] Casts of a non-nullable bottom type to non-null fail (#5645)Alon Zakai2023-04-121-6/+4
| | | | | | | | | | | Casting (ref nofunc) to (ref func) seems like it can succeed based on the rule of "if it's a subtype, it can cast ok." But the fuzzer found a corner case where that leads to a validation error (see testcase). Refactor the cast evaluation logic to handle uninhabitable refs directly, and return Unreachable for them (since the cast cannot even be reached). Also reorder the rule checks there to always check for a non-nullable cast of a bottom type (which always fails).
* [NFC] Refactor some old fuzzer code (#5658)Alon Zakai2023-04-121-13/+8
| | | | A return value was unused, and we have BranchUtils::operateOnScopeNameDefs now which can replace old manual code.
* [NFC] Refactor fuzzer array check logic (#5659)Alon Zakai2023-04-121-20/+30
|
* Fuzzer: When nested under makeTrivial(), avoid normal make() (#5657)Alon Zakai2023-04-121-0/+12
| | | | | | | | Without this, in certain complex operations we could end up calling a nested make() operation that included nontrivial things, which could cause problems. The specific problem I encountered was in fixAfterChanges() we tried to fix up a duplicate label, but calling makeTrivial() emitted something very large that happened to include a new block with a new label nested under a struct.get, and that block's label conflicted with a label we'd already processed.
* [Wasm GC] Fuzz struct.set and array.set (#5655)Alon Zakai2023-04-121-1/+65
|
* [Wasm GC] Fuzz struct.get and array.get (#5651)Alon Zakai2023-04-101-0/+62
|
* Fuzzer: Improve mutate() (#5631)Alon Zakai2023-04-051-9/+33
| | | Don't use a fixed 10% chance to mutate, but pick a mutation rate in each function.
* Avoid imported memories in the fuzzer (#5626)Alon Zakai2023-04-051-12/+15
| | | | | | | We already did this for the first memory, and just needed to loop to handle initial content in the test suite that has multiple memories. Also clean up that code while I'm around, to avoid repeating wasm.memories[0] all the time.
* [Wasm GC] Fuzz struct.new and array.new (#5622)Alon Zakai2023-04-041-23/+36
| | | | | | | | | Repurpose makeBasicRef, makeCompoundRef to generate not just "constant" refs but any reference, and use those to create StructNew/ArrayNew. The key changes are to add makeCompoundRef to make(), and to make the function call make() for children, where possible, instead of just makeTrivial(). We also replace the i31-specific path with a call to makeBasicRef which handles i31 among other things.
* Use Names instead of indices to identify segments (#5618)Thomas Lively2023-04-041-5/+9
| | | | | | | | | | All top-level Module elements are identified and referred to by Name, but for historical reasons element and data segments were referred to by index instead. Fix this inconsistency by using Names to refer to segments from expressions that use them. Also parse and print segment names like we do for other elements. The C API is partially converted to use names instead of indices, but there are still many functions that refer to data segments by index. Finishing the conversion can be done in the future once it becomes necessary.
* [Wasm GC] Fuzz RefCast (#5617)Alon Zakai2023-04-031-7/+82
|
* Ensure a deterministic order in the type names section (#5590)Alon Zakai2023-03-201-0/+5
| | | | | | | | | Before this PR we iterated over an unordered set. Replace that with an iteration on a vector. (Also, the value in the set was not even used, so this should even be faster.) Add random names in the fuzzer to types, the lack of which is I believe the reason this was not detected before.
* [Wasm GC] Fuzz ref.test (#5577)Alon Zakai2023-03-161-0/+37
|
* Fuzzer: Generate both immutable and mutable globals (#5575)Alon Zakai2023-03-151-3/+7
|
* Fuzzer: Pick interesting subtypes in getSubType(HeapType) (#5573)Alon Zakai2023-03-151-7/+34
|
* Fix fuzzer emitting invalid constant expressions (#5571)Thomas Lively2023-03-131-19/+21
| | | | | | | | | | The fuzzer had code to avoid emitting `global.get` of locally defined (i.e. non-imported) globals in global initializers and data segment offsets, but that code only handled top-level `global.get` because it predated the extended-const proposal. Unfortunately this bug went undetected until #5557, which fixed the validator to make it reject invalid uses of `global.get` in constant expressions. Fix the bug so the validator no longer produces invalid modules.
* Fuzzer: Avoid emitting massive nested structs (#5564)Alon Zakai2023-03-131-7/+26
| | | | | | | | | | | The nesting limit of around 20 was enough to cause exponential blowup. A 20K input file lead to a 2GB wasm in one case I saw (!) which takes many seconds to fuzz. Instead, reduce the limit, and also check if random tells us that the random input is done; when that's done we should stop, which limits us to O(input size). Also do this for non-nullable types, and handle that in globals (we cannot emit a RefAsNulNull there, so switch the global type if necessary).
* Fuzzer: Limit array sizes (#5569)Alon Zakai2023-03-131-10/+1
| | | | | | Even with a 1% chance of a huge array, there is a second problem aside from hitting an allocation failure, which is DoS - building such a huge array of Literals takes noticeable time in the fuzzer. Instead, just limit array max sizes, which is consistent with what we do for struct sizes etc.
* Fuzzer: Emit fewer uninhabitable types in getSubType (#5563)Alon Zakai2023-03-101-0/+9
| | | | Only rarely return an uninhabitable subtype of an inhabitable one. This avoids a major source of uninhabitability and immediate traps.
* Fuzzer: Emit nulls with low probability in makeConstCompoundRef (#5559)Alon Zakai2023-03-101-18/+17
| | | | In particular, the removed code path here that did a RefAsNonNull of a null was causing a lot of code to just trap.
* Emit the fuzzer hashMemory function after modifications (#5558)Alon Zakai2023-03-091-47/+53
| | | | | | | | | | Previously we emitted it early, and would then modify it in random ways like other initial content. But this function is called frequently during execution, so if we were unlucky and modded that function to trap then basically all other functions would trap as well. After fixing this, some places assert on not having any functions or types to pick a random one from, so fix those places too.
* Integrate the heap type fuzzer into the main fuzzer (#5555)Alon Zakai2023-03-091-2/+30
| | | | | | | | | | | | | With this we generate random GC types that may be used in creating instructions later. We don't create many instructions yet, which will be the next step after this. Also add some trivial assertions in some places, that have helped debugging in the past. Stop fuzzing TypeMerging for now due to #5556 , which this PR uncovers.
* Fuzzer: Pick from existing heap types in the module (#5539)Alon Zakai2023-03-081-5/+42
|
* Fuzzer: Be careful with ArrayNew sizes (#5537)Alon Zakai2023-03-011-1/+11
| | | | Only very rarely ask to create a huge array, as that can easily hit a host size limit and cause a run to be ignored.
* Fuzzer: Only use RefAs in a function context (#5533)Alon Zakai2023-03-011-1/+4
| | | It is not a constant instruction and cannot be used in globals.
* Fuzzer: Create struct/array initial values when fields are nondefaultable ↵Alon Zakai2023-03-011-4/+18
| | | | (#5529)
* Fuzzer: Avoid local.get when not in a function (#5528)Alon Zakai2023-03-011-1/+1
|
* [NFC] Internally rename `ArrayInit` to `ArrayNewFixed` (#5526)Thomas Lively2023-02-281-1/+1
| | | | | | | | To match the standard instruction name, rename the expression class without changing any parsing or printing behavior. A follow-on PR will take care of the functional side of this change while keeping support for parsing the old name. This change will allow `ArrayInit` to be used as the expression class for the upcoming `array.init_data` and `array.init_elem` instructions.
* [Fuzzer] Simplify the hang limit mechanism (#5513)Alon Zakai2023-02-231-21/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously the idea was that we started with HANG_LIMIT = 10 or so, and we'd decrement it by one in each potentially-recursive call and loop entry. When we reached 0 we'd start to unwind the stack. Then, after we unwound it all the way, we'd reset HANG_LIMIT before calling the next export. That approach adds complexity that each "execution wrapper", like for JS or for --fuzz-exec, had to manually reset HANG_LIMIT. That was done by calling an export. Calls to those exports had to appear in various places, which is sort of a hack. The new approach here does the following when the hang limit reaches zero: It resets HANG_LIMIT, and it traps. The trap unwinds the call stack all the way out. When the next export is called, it will have a fresh hang limit since we reset it before the trap. This does have downsides. Before, we did not always trap when we hit the hang limit but rather we'd emit something unreachable, like a return. The idea was that we'd leave the current function scope at least, so we don't hang forever. That let us still execute a small amount of code "on the way out" as we unwind the stack. I'm not sure it's worth the complexity for that. The advantages of this PR are to simplify the code, and also it makes more fuzzing approaches easy to implement. I'd like to add a wasm-ctor-eval fuzzer, and having to add hacks to call the hang limit init export in it would be tricky. With this PR, the execution model is simple in the fuzzer: The exports are called one by one, in order, and that's it - no extra magic execution needs to be done. Also bump the hang limit from 10 to 100, just to give some more chance for code to run.
* [Strings] Start some basic fuzzing support for strings (#5499)Alon Zakai2023-02-171-0/+2
| | | | | This is necessary to avoid fuzzer breakage after #5497 as it added a test with strings. We could also ignore that file, like we do for other string files, but this was not much work so just implement it.
* Fuzzer: Be more careful with unreachable code (#5498)Alon Zakai2023-02-161-3/+9
| | | | Half the time, never add any unreachable code. This ensures we run the most code we possibly can half the time, at least.
* Fuzzer: Replace with unreachable sometimes (#5496)Alon Zakai2023-02-161-12/+19
| | | | | | | | | | | | | This makes the fuzzer replace things with an unreachable instruction in rare situations. The hope was to find bugs like #5487, but instead it's mostly found bugs in the inliner actually (#5492, #5493). This also fixes an uncovered bug in the fuzzer, where we refinalized in more than one place. It is unsafe to do so before labels are fixed up (as duplicate labels can confuse us as to which types are needed; this is actually the same issue as in #5492). To fix that, remove the extra refinalize that was too early, and also rename the fixup function since it does a general fixup for all the things.
* [Wasm GC] Support and fuzz function subtyping (#5420)Thomas Lively2023-01-121-1/+1
| | | | | | | | | | Support function subtyping with contravariant parameters and covariant results. The actual change is a single line in wasm-type.cpp, so most of the patch is updating the type fuzzer to generate interesting function subtypes. Since function parameters are covariant, generating a function subtype requires generating supertypes of its parameter types, which required new functionality in the fuzzer. Also update the fuzzer to choose to reuse types at a finer grain, so for example individual function parameters or results might be reused unmodified while other parameters or results are still modified.