Repository navigation
Conversation
MaybeUseAndBindName() derives a name from an import or export name and loops on a disambiguating suffix until the result is not already bound. The writer then replaces every character a name cannot contain with '_', so two export names differing only in those characters produce the same text however many times that loop runs: the loop compares a string that is not the one written. wasm2wat --generate-names on a module exporting "a b", "a,b" and "a(b" writes three functions all called $a_b, and wat2wasm rejects its own output with "redefinition of function". names.wast in the spec testsuite hits this, with 512 functions written as $___. Move the replacement into MakeValidWatName() next to the table it uses, and settle on the written form before the loop compares it, so the suffix is applied to names that would otherwise collide. This does not cover a name that came from the binary's name section rather than being generated here; those are written as-is and can still collide.
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.
wasm2wat --generate-namescan write a module thatwat2wasmthen refuses:The module exports three functions named
"a b","a,b"and"a(b", and allthree come out as
$a_b.Why
MaybeUseAndBindName()derives a name from an import or export name and loopson a disambiguating suffix until the result is not already bound:
WatWriter::WriteName()then replaces every character a name cannot containwith
_. So the loop compares$a b,$a,band$a(b, finds no clash andnever applies a suffix, and the writer turns all three into
$a_b. Thedisambiguator cannot disambiguate, because the string it tests is not the
string that gets written.
names.wastin the spec testsuite runs into this: 512 of its functions arewritten as
$___, 242 as$____and 86 as$__, and the output does notassemble.
The change
Move the replacement out of
WriteName()intoMakeValidWatName(), declarednext to
WriteWat()since it is part of what the writer guarantees about itsoutput, and call it in the loop before the comparison. The suffix is then
applied to exactly the names that would otherwise be written the same.
The three exports above now come out as
$a_b,$a_b_1and$a_b_2, and theoutput assembles.
What this does not cover
A name that came from the binary's name section is used as-is rather than
generated here, so two of those differing only in these characters still
collide, and this affects plain
wasm2watas well as--generate-names:A reference is ambiguous too: with a fourth function calling the second, the
output contains
call $a_bwith two definitions of that name.I left that alone deliberately. Fixing it means renaming entities the module
itself named, and doing it before
ApplyNames()runs so the vars pick the newnames up, which is a different and more visible change than correcting a
disambiguation loop that cannot currently work. Happy to follow up with it, or
open it as an issue instead, whichever you prefer.
Verification
test/binary/generate-names-invalid-chars.txtcovers the generated-name case.On current main it fails with:
and passes with the change. I also checked that the expected output assembles,
which is the property that was actually broken.
For the suite I compared against a baseline rather than reading the output,
since
wat2wasm_stdout.txtfails on unmodified main on this machine for itsown reasons. Unmodified main fails that one test; with the change it is still
the only failure, so nothing moved.
clang-format --dry-run --Werroris cleanon the three changed files.
How I ran into it: I was sweeping
wat-desugarover everythingwast2jsonextracts from
third_party/testsuite, checking that desugaring preserves whata module assembles to and is idempotent, across its output options. All 1731
modules pass both properties for no options,
--fold-exprs,--inline-importsand the two combined.
--generate-nameswas the one option that produced textwhich no longer assembles, on one module, which turned out to be this.