Skip to content

[Fuzzer] Handle uninhabitable types in makeCompoundRef - #9282

Merged
tlively merged 8 commits into
mainfrom
fuzzer-compound-ref-recursion
Oct 22, 2026
Merged

tlively merged 8 commits into
mainfrom
fuzzer-compound-ref-recursion

Conversation

@tlively

@tlively tlively commented Oct 20, 2026

Copy link
Copy Markdown
Member

Uninhabitable heap types from the initial module are filtered out of interestingHeapTypes in setupHeapTypes, but inhabitable types in interestingHeapTypes (as well as initial module globals and functions) can still reference them. Track uninhabitableHeapTypes in TranslateToFuzzReader and check for them in makeCompoundRef, getSubType, and getSuperType so makeCompoundRef emits ref.null, local.get, or ref.as_non_null rather than infinitely recursing across non-nullable type cycles.

Uninhabitable heap types from the initial module are filtered out of interestingHeapTypes in setupHeapTypes, but inhabitable types in interestingHeapTypes (as well as initial module globals and functions) can still reference them. Track uninhabitableHeapTypes in TranslateToFuzzReader and check for them in makeCompoundRef, getSubType, and getSuperType so makeCompoundRef emits ref.null, local.get, or ref.as_non_null rather than infinitely recursing across non-nullable type cycles.
@tlively
tlively requested a review from a team as a code owner October 20, 2026 02:27
@tlively
tlively requested review from stevenfontanella and removed request for a team October 20, 2026 02:27

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request prevents infinite recursion in makeCompoundRef during fuzzing by tracking and handling uninhabitable heap types from the initial module contents. It populates a set of uninhabitable heap types and checks it when generating compound references, falling back to null references or non-null cast escape hatches. A helper method isUninhabitable is also introduced and used during sub/supertype generation. Feedback on the changes points out a potential assertion failure in isUninhabitable when called with non-reference types, recommending a check for type.isRef() before retrieving the heap type.

Comment on lines +6883 to +6887
bool TranslateToFuzzReader::isUninhabitable(Type type) {
return GCTypeUtils::isUninhabitable(type) ||
(type.isRef() && type.isNonNullable() &&
uninhabitableHeapTypes.contains(type.getHeapType()));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In Binaryen, Type::isNonNullable() can return true for non-reference types (such as basic types like i32 or f64), but calling Type::getHeapType() on a non-reference type will trigger an assertion failure in debug builds. Since GCTypeUtils::isUninhabitable(type) internally calls type.getHeapType() without checking type.isRef(), calling TranslateToFuzzReader::isUninhabitable on a non-reference type would result in an assertion failure.\n\nTo make this method robust and defensively guard against non-reference types, we should check type.isRef() first before calling GCTypeUtils::isUninhabitable(type) or accessing its heap type.

bool TranslateToFuzzReader::isUninhabitable(Type type) {\n  return type.isRef() &&\n         (GCTypeUtils::isUninhabitable(type) ||\n          (type.isNonNullable() &&\n           uninhabitableHeapTypes.contains(type.getHeapType())));\n}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Binaryen, Type::isNonNullable() can return true for non-reference types (such as basic types like i32 or f64)...

This is not true. Type::isNonNullable() is defined like this:

  bool isNonNullable() const { return isRef() && !(id & NullMask); }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On that note it looks like the check for isRef here is redundant, can we remove it? Separately it'd be nice to rename isNonNullable to isNonNullableRef in another PR.

@stevenfontanella stevenfontanella left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after comments

Comment thread src/tools/fuzzing/fuzzing.cpp Outdated
Comment thread src/tools/fuzzing/fuzzing.cpp
@tlively
tlively enabled auto-merge (squash) October 20, 2026 21:02
@tlively

tlively commented Oct 22, 2026

Copy link
Copy Markdown
Member Author

@stevenfontanella, it turned out that there were some other ways for uninhabitable types to slip in. PTAL at the latest changes to fix that.

@stevenfontanella

Copy link
Copy Markdown
Member

The CI failure looks real, can you take a look? fuzz-uninhabitable.wast shows a diff

@tlively

tlively commented Oct 22, 2026

Copy link
Copy Markdown
Member Author

Yep, fixed now.

Comment on lines +12 to +13
;; only imports a random subset of heap types and the fuzzer may not choose to
;; construct $2 for every random input seed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something, can we add a seed here to make it deterministic and then check the output here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of. The previous version of the test did this by using the test file contents itself as the seed. The problem was that on Windows the line endings were read differently, leading to different random choices and the CI failure you saw.

Another problem is that future fuzzer changes could also change the random choices, creating an ongoing maintenance burden if this test starts failing as a result.

@tlively
tlively merged commit 10b1b0d into main Oct 22, 2026
16 of 17 checks passed
@tlively
tlively deleted the fuzzer-compound-ref-recursion branch October 22, 2026 19:15
@tlively

tlively commented Oct 22, 2026 •

Copy link
Copy Markdown
Member Author

Sorry, I don't think I meant to merge this :/ Looks like I had auto-merge enabled since a couple days ago and forgot to turn it off. Happy to continue addressing any comments in a follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants