diff options
author | Alon Zakai <azakai@google.com> | 2023-03-10 09:30:46 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-10 09:30:46 -0800 |
commit | a3cc3a514a754cf8d505806055194622606893f1 (patch) | |
tree | 5c514d4986c23bbda2f968636988feaa321f6e1a /src/tools/fuzzing/fuzzing.cpp | |
parent | ed8621953c9c1165512ca83d8804289184bb6f22 (diff) | |
download | binaryen-a3cc3a514a754cf8d505806055194622606893f1.tar.gz binaryen-a3cc3a514a754cf8d505806055194622606893f1.tar.bz2 binaryen-a3cc3a514a754cf8d505806055194622606893f1.zip |
Fuzzer: Emit nulls with low probability in makeConstCompoundRef (#5559)
In particular, the removed code path here that did a RefAsNonNull of a null
was causing a lot of code to just trap.
Diffstat (limited to 'src/tools/fuzzing/fuzzing.cpp')
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index db4d0196e..7d663641e 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -2172,28 +2172,27 @@ Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) { auto heapType = type.getHeapType(); assert(!heapType.isBasic()); assert(wasm.features.hasReferenceTypes()); - if (heapType.isSignature()) { - return makeRefFuncConst(type); - } - // We weren't able to directly materialize a non-null constant. Try again to - // create a null. - if (type.isNullable()) { + // Prefer not to emit a null, in general, as we can trap from them. If it is + // nullable, give a small chance to do so; if we hit the nesting limit then we + // really have no choice and must emit a null (or else we could infinitely + // recurse). For the nesting limit, use a bound that is higher than the normal + // one, so that the normal mechanisms should prevent us from getting here; + // this limit is really a last resort we want to never reach. + // + // Note that we might have cycles of types where some are non-nullable. We + // will only stop here when we exceed the nesting and reach a nullable one. + // (This assumes there is a nullable one, that is, that the types are + // inhabitable.) + const auto LIMIT = 2 * NESTING_LIMIT; + AutoNester nester(*this); + if (type.isNullable() && (oneIn(10) || nesting >= LIMIT)) { return builder.makeRefNull(heapType); } - // We have to produce a non-null value. Possibly create a null and cast it - // to non-null even though that will trap at runtime. We must have a - // function context for this because the cast is not allowed in globals. - if (funcContext) { - return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType)); - } - - // Otherwise, we are not in a function context. This can happen if we need - // to make a constant for the initializer of a global, for example. We've - // already handled simple cases of this above, for basic heap types, so what - // we have left here are user-defined heap types like structs. - if (type.isStruct()) { + if (heapType.isSignature()) { + return makeRefFuncConst(type); + } else if (type.isStruct()) { auto& fields = heapType.getStruct().fields; std::vector<Expression*> values; // TODO: use non-default values randomly even when not necessary, sometimes |