diff options
author | Alon Zakai <azakai@google.com> | 2023-04-12 13:30:27 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-12 20:30:27 +0000 |
commit | 958daad07e69ad37ab0575a08559f143e96b169b (patch) | |
tree | 098553dfba74562bebcfc1edfe3e22e729267cb8 /src | |
parent | 1d1d60c6d9803edb2e3684c69c0298d7e5b2d8cb (diff) | |
download | binaryen-958daad07e69ad37ab0575a08559f143e96b169b.tar.gz binaryen-958daad07e69ad37ab0575a08559f143e96b169b.tar.bz2 binaryen-958daad07e69ad37ab0575a08559f143e96b169b.zip |
Fuzzer: When nested under makeTrivial(), avoid normal make() (#5657)
Without this, in certain complex operations we could end up calling a nested
make() operation that included nontrivial things, which could cause problems.
The specific problem I encountered was in fixAfterChanges() we tried to fix up
a duplicate label, but calling makeTrivial() emitted something very large that
happened to include a new block with a new label nested under a struct.get,
and that block's label conflicted with a label we'd already processed.
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/fuzzing.h | 4 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 12 |
2 files changed, 16 insertions, 0 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index f055d7f44..c0f6ab335 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -271,6 +271,10 @@ private: // Make something with no chance of infinite recursion. Expression* makeTrivial(Type type); + // We must note when we are nested in a makeTrivial() call. When we are, all + // operations must try to be as trivial as possible. + int trivialNesting = 0; + // Specific expression creators Expression* makeBlock(Type type); Expression* makeLoop(Type type); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 1c2b818df..d062dd5c8 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -1060,6 +1060,10 @@ void TranslateToFuzzReader::addInvocations(Function* func) { Expression* TranslateToFuzzReader::make(Type type) { auto subtype = getSubType(type); + if (trivialNesting) { + // We are nested under a makeTrivial call, so only emit something trivial. + return makeTrivial(type); + } // When we should stop, emit something small (but not necessarily trivial). if (random.finished() || nesting >= 5 * NESTING_LIMIT || // hard limit (nesting >= NESTING_LIMIT && !oneIn(3))) { @@ -1226,6 +1230,14 @@ Expression* TranslateToFuzzReader::_makeunreachable() { } Expression* TranslateToFuzzReader::makeTrivial(Type type) { + struct TrivialNester { + TranslateToFuzzReader& parent; + TrivialNester(TranslateToFuzzReader& parent) : parent(parent) { + parent.trivialNesting++; + } + ~TrivialNester() { parent.trivialNesting--; } + } nester(*this); + if (type.isConcrete()) { if (oneIn(2) && funcContext) { return makeLocalGet(type); |