diff options
Diffstat (limited to 'src/tools/fuzzing/fuzzing.cpp')
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index b7d075dcc..5dcdc66d5 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -178,6 +178,9 @@ void TranslateToFuzzReader::build() { setupTags(); addImportThrowingSupport(); } + if (wasm.features.hasReferenceTypes()) { + addImportTableSupport(); + } addImportLoggingSupport(); modifyInitialFunctions(); // keep adding functions until we run out of input @@ -609,6 +612,49 @@ void TranslateToFuzzReader::addImportThrowingSupport() { wasm.addFunction(std::move(func)); } +void TranslateToFuzzReader::addImportTableSupport() { + // For the table imports to be able to do anything, we must export a table + // for them. For simplicity, use the funcref table we use internally, though + // we could pick one at random, support non-funcref ones, and even export + // multiple ones TODO + if (!funcrefTableName) { + return; + } + + // If a "table" export already exists, skip fuzzing these imports, as the + // current export may not contain a valid table for it. + if (wasm.getExportOrNull("table")) { + return; + } + + // Export the table. + wasm.addExport( + builder.makeExport("table", funcrefTableName, ExternalKind::Table)); + + // Get from the table. + { + tableGetImportName = Names::getValidFunctionName(wasm, "table-get"); + auto func = std::make_unique<Function>(); + func->name = tableGetImportName; + func->module = "fuzzing-support"; + func->base = "table-get"; + func->type = Signature({Type::i32}, Type(HeapType::func, Nullable)); + wasm.addFunction(std::move(func)); + } + + // Set into the table. + { + tableSetImportName = Names::getValidFunctionName(wasm, "table-set"); + auto func = std::make_unique<Function>(); + func->name = tableSetImportName; + func->module = "fuzzing-support"; + func->base = "table-set"; + func->type = + Signature({Type::i32, Type(HeapType::func, Nullable)}, Type::none); + wasm.addFunction(std::move(func)); + } +} + void TranslateToFuzzReader::addHashMemorySupport() { // Add memory hasher helper (for the hash, see hash.h). The function looks // like: @@ -722,6 +768,21 @@ Expression* TranslateToFuzzReader::makeImportThrowing(Type type) { return builder.makeCall(throwImportName, {}, Type::none); } +Expression* TranslateToFuzzReader::makeImportTableGet() { + assert(tableGetImportName); + return builder.makeCall( + tableGetImportName, {make(Type::i32)}, Type(HeapType::func, Nullable)); +} + +Expression* TranslateToFuzzReader::makeImportTableSet(Type type) { + assert(type == Type::none); + assert(tableSetImportName); + return builder.makeCall( + tableSetImportName, + {make(Type::i32), makeBasicRef(Type(HeapType::func, Nullable))}, + Type::none); +} + Expression* TranslateToFuzzReader::makeMemoryHashLogging() { auto* hash = builder.makeCall(std::string("hashMemory"), {}, Type::i32); return builder.makeCall(logImportNames[Type::i32], {hash}, Type::none); @@ -1489,6 +1550,9 @@ Expression* TranslateToFuzzReader::_makenone() { .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeBrOn) .add(FeatureSet::ReferenceTypes | FeatureSet::GC, &Self::makeArrayBulkMemoryOp); + if (tableSetImportName) { + options.add(FeatureSet::ReferenceTypes, &Self::makeImportTableSet); + } return (this->*pick(options))(Type::none); } @@ -2679,6 +2743,12 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { return null; } case HeapType::func: { + // Rarely, emit a call to imported table.get (when nullable, unshared, and + // where we can emit a call). + if (type.isNullable() && share == Unshared && funcContext && + tableGetImportName && !oneIn(3)) { + return makeImportTableGet(); + } return makeRefFuncConst(type); } case HeapType::cont: { |