summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-04-12 13:30:27 -0700
committerGitHub <noreply@github.com>2023-04-12 20:30:27 +0000
commit958daad07e69ad37ab0575a08559f143e96b169b (patch)
tree098553dfba74562bebcfc1edfe3e22e729267cb8 /src
parent1d1d60c6d9803edb2e3684c69c0298d7e5b2d8cb (diff)
downloadbinaryen-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.h4
-rw-r--r--src/tools/fuzzing/fuzzing.cpp12
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);