summaryrefslogtreecommitdiff
path: root/src/tools/fuzzing/fuzzing.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-03-10 09:30:46 -0800
committerGitHub <noreply@github.com>2023-03-10 09:30:46 -0800
commita3cc3a514a754cf8d505806055194622606893f1 (patch)
tree5c514d4986c23bbda2f968636988feaa321f6e1a /src/tools/fuzzing/fuzzing.cpp
parented8621953c9c1165512ca83d8804289184bb6f22 (diff)
downloadbinaryen-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.cpp35
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