Repository navigation
Conversation
jrandolf
force-pushed
the
wasm-smith-component-grammar
branch
3 times, most recently
from
October 23, 2026 23:03
2181f49 to
96fa573
Compare
Outer aliases now print the same identifier as the header of the component they refer to, or its count when a scope in between has the same identifier. They printed the target's name with its `(@name ...)` annotation, which only parses where the component is defined; they used a nested component's own name from its `component-name` section, while its header uses the name its parent gives it; and they printed identifiers that an inner scope shadows, such as the synthetic `$"#component0 "` of both a component and its first nested component, so the printed text didn't parse or referred to the wrong scope. (component (@name "") (type u8) (alias outer 0 0 (type))) printed `(alias outer $"#component0 " (@name "") 0 (type))`.
jrandolf
force-pushed
the
wasm-smith-component-grammar
branch
from
October 23, 2026 23:52
96fa573 to
1d08bd1
Compare
Names that separate `component-name` (or `name`) subsections gave the same index space were each deduplicated on their own, so two items could print the same identifier and the printed text didn't parse, as with two `component-name` sections that each name a different core function `a`. A name that an earlier subsection gave another index is now taken too.
`WellFormedComponent` emits a derivation of the `component` production of the component model's binary grammar, with one method per production, so it always decodes. Indices are in bounds whenever their index space isn't empty, and `Config::component_steering_percent` of the other choices that can lead to a valid component do: at 0 components only follow the grammar, and at 100 nearly all of them validate. For that, each scope tracks the kinds of its types, how value types flatten, the types of functions and core functions, which types are named, and what modules, components, instances and their types import and export. Names are drawn from pools that `Config::name_pool_size`, `name_reuse_percent` and `name_collision_percent` configure, so that references by name line up and names collide. Core modules come from `Module`, which a crate-internal `Shape` makes import and export what a component lifts and lowers when steered. This sits alongside the existing `Component` generator, which generates valid components but is disabled. The new `well_formed_component` fuzz target checks that every generated component decodes, that validating and printing it doesn't panic, and that valid ones round-trip through the text format. Productions that `wasmparser` doesn't decode as specified aren't generated: value definitions and `valuebound`s (🪙), and the 🧵② built-ins, whose `sh?` immediate `wasmparser` doesn't read. Neither are start definitions (🪙), since the text format can't hold the names that `wasmprinter` prints for their results. Recursion groups aren't generated in component and instance types, where `wast` doesn't parse the `(core rec ...)` that `wasmprinter` prints.
jrandolf
force-pushed
the
wasm-smith-component-grammar
branch
from
October 24, 2026 04:01
1d08bd1 to
423069e
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Components are currently only fuzzed as raw bytes, since the
wasm-smithcomponent generator is disabled (#1000). This addswasm_smith::WellFormedComponent, which emits a derivation of thecomponentproduction of the binary grammar, one method per production, and steers its choices toward a valid component as often as the newConfig::component_steering_percentsays. At 0, components only follow the grammar, with indices in bounds, and about a third of them validate (mostly small ones); at 100, about 98% of them validate.How components are generated
vec(...)orsection*repeats. Size and count prefixes are written once the bytes they cover exist, and the grammar's side conditions (non-empty records, at most 32 flags, map key types, the text format's grammar for names) are generated directly. Wherewasmparserchecks a validation rule while decoding (the sorts that exports can have, unique attributes, sorted name maps), generation follows it so that decoding never fails.memory,realloc,post-returnandcallbackoptions it needs, and lower functions with the options that their type needs;eqbounds and function types whose types are named;[constructor],[method],[static]and accessor names only to functions whose types fit;Module. When steered, they only import functions that a core instance exports, and they export a memory, areallocand functions of the types that lifting the scope's function types needs (through a crate-internalShapeincore.rs).Config::name_pool_sizenames and are reusedConfig::name_reuse_percentof the time.Config::name_collision_percentof the names that collide in a scope are kept rather than replaced, and as often a new name is a variant of a pooled one that differs only in case, so that strong uniqueness is checked.The
well_formed_componentfuzz target checks that every component decodes, that validating and printing it doesn't panic, and that valid ones round-trip through the text format. It picks the settings per input, steering from 80 to 100 three times in four, and about 58% of its components validate. On 20,000 random inputs, it covers 69% of the lines of the component validator and 92% of the component printer, against 27% and 46% for the disabledComponentgenerator.This builds on #2795, which fixes the printer bugs that this fuzzer found, and includes its commit until it merges. It also includes one more printer fix that the fuzzer found since: names that separate
component-namesubsections give the same index space could print as the same identifier, as with twocomponent-namesections that each name a different core functiona.Productions that
wasmparserdoesn't decode as specified aren't generated:externtype0x02is followed by avaluebound(0x00 valueidxor0x01 valtype) sincecomponent-model@4480daf, butwasmparserreads avaltypedirectly.thread.spawn-ref,thread.spawn-indirectandthread.available-parallelismtake ash?immediate sincecomponent-model#557, whichwasmparserdoesn't read.Start definitions (🪙) aren't generated either, since the text format can't hold the names that
wasmprinterprints for their results. Recursion groups also aren't generated in component and instance types, wherewastdoesn't parse the(core rec ...)thatwasmprinterprints until #2798.