From 9ddbe646a8593bd27dd580d46a383b1b297c6739 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 4 Nov 2025 11:21:19 -0800 Subject: [PATCH 1/2] fix --- src/tools/fuzzing/fuzzing.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 5c0fc8268ff..fc015a7adda 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -712,7 +712,8 @@ void TranslateToFuzzReader::setupGlobals() { assert(init->is()); } if (!FindAll(init).list.empty() || - !FindAll(init).list.empty()) { + !FindAll(init).list.empty() || + !FindAll(init).list.empty()) { // When creating this initial value we ended up emitting a RefAs, which // means we had to stop in the middle of an overly-nested struct or array, // which we can break out of using ref.as_non_null of a nullable ref. That @@ -720,7 +721,8 @@ void TranslateToFuzzReader::setupGlobals() { // validate in a global. Switch to something safe instead. // // Likewise, if we see cont.new, we must switch as well. That can happen - // if a nested struct we create has a continuation field, for example. + // if a nested struct we create has a continuation field, for example. And + // for non-nullable exnrefs, we end up with a throw in a block. type = getMVPType(); init = makeConst(type); } @@ -3795,13 +3797,15 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { return builder.makeArrayNewFixed(ht, {}); } case HeapType::exn: { - // If nullable, we can emit a null. If there is no function context, then - // we must do so, as the other option is a throw in a block, which are not - // possible outside of functions. - if ((type.isNullable() && oneIn(2)) || !funcContext) { + // If nullable, sometimes emit a null (always, if nullable and we are not + // in a function context). + if (type.isNullable() && (!funcContext || oneIn(2))) { return builder.makeRefNull(HeapTypes::exn.getBasic(share)); } + // Emit a throw in a block. Note that this is invalid if there is no + // function context, in which case the calling code will handle that (as + // it does for RefAsNonNull and other fixups). auto* throww = makeThrow(Type::unreachable); auto label = makeLabel(); auto* tryy = builder.makeTryTable(throww, {Name()}, {label}, {true}); From 5886f3b7ff8e848b8fe8c023078abbd20b44ccea Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 4 Nov 2025 11:30:30 -0800 Subject: [PATCH 2/2] fix --- src/tools/fuzzing/fuzzing.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index fc015a7adda..3acbc0f032b 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -712,8 +712,7 @@ void TranslateToFuzzReader::setupGlobals() { assert(init->is()); } if (!FindAll(init).list.empty() || - !FindAll(init).list.empty() || - !FindAll(init).list.empty()) { + !FindAll(init).list.empty()) { // When creating this initial value we ended up emitting a RefAs, which // means we had to stop in the middle of an overly-nested struct or array, // which we can break out of using ref.as_non_null of a nullable ref. That @@ -721,8 +720,7 @@ void TranslateToFuzzReader::setupGlobals() { // validate in a global. Switch to something safe instead. // // Likewise, if we see cont.new, we must switch as well. That can happen - // if a nested struct we create has a continuation field, for example. And - // for non-nullable exnrefs, we end up with a throw in a block. + // if a nested struct we create has a continuation field, for example. type = getMVPType(); init = makeConst(type); } @@ -3797,15 +3795,21 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { return builder.makeArrayNewFixed(ht, {}); } case HeapType::exn: { - // If nullable, sometimes emit a null (always, if nullable and we are not - // in a function context). - if (type.isNullable() && (!funcContext || oneIn(2))) { - return builder.makeRefNull(HeapTypes::exn.getBasic(share)); + // If nullable, sometimes emit a null. If not in a function context, see + // below, we need a null as well regardless of the type. + if ((type.isNullable() && oneIn(2)) || !funcContext) { + auto* null = builder.makeRefNull(HeapTypes::exn.getBasic(share)); + if (type.isNullable()) { + return null; + } + // The type is non-nullable, so we are here because we are in a non- + // function context, with nothing valid to emit. "Fix" it with a cast, + // which is not valid IR, but which the calling code will handle. + assert(!funcContext); + return builder.makeRefAs(RefAsNonNull, null); } - // Emit a throw in a block. Note that this is invalid if there is no - // function context, in which case the calling code will handle that (as - // it does for RefAsNonNull and other fixups). + // Emit a throw in a block. auto* throww = makeThrow(Type::unreachable); auto label = makeLabel(); auto* tryy = builder.makeTryTable(throww, {Name()}, {label}, {true});