@@ -614,10 +614,12 @@ void TranslateToFuzzReader::setupGlobals() {
614614 // run the wasm.
615615 for (auto & global : wasm.globals ) {
616616 if (global->imported ()) {
617- // Remove import info from imported globals, and give them a simple
618- // initializer.
619- global->module = global->base = Name ();
620- global->init = makeConst (global->type );
617+ if (!preserveImportsAndExports) {
618+ // Remove import info from imported globals, and give them a simple
619+ // initializer.
620+ global->module = global->base = Name ();
621+ global->init = makeConst (global->type );
622+ }
621623 } else {
622624 // If the initialization referred to an imported global, it no longer can
623625 // point to the same global after we make it a non-imported global unless
@@ -695,7 +697,7 @@ void TranslateToFuzzReader::setupTags() {
695697 // As in modifyInitialFunctions(), we can't allow arbitrary tag imports, which
696698 // would trap when the fuzzing infrastructure doesn't know what to provide.
697699 for (auto & tag : wasm.tags ) {
698- if (tag->imported ()) {
700+ if (tag->imported () && !preserveImportsAndExports ) {
699701 tag->module = tag->base = Name ();
700702 }
701703 }
@@ -707,7 +709,7 @@ void TranslateToFuzzReader::setupTags() {
707709 }
708710
709711 // Add the fuzzing support tags manually sometimes.
710- if (oneIn (2 )) {
712+ if (!preserveImportsAndExports && oneIn (2 )) {
711713 auto wasmTag = builder.makeTag (Names::getValidTagName (wasm, " wasmtag" ),
712714 Signature (Type::i32 , Type::none));
713715 wasmTag->module = " fuzzing-support" ;
@@ -779,9 +781,12 @@ void TranslateToFuzzReader::finalizeMemory() {
779781 memory->max =
780782 std::min (Address (memory->initial + 1 ), Address (Memory::kMaxSize32 ));
781783 }
782- // Avoid an imported memory (which the fuzz harness would need to handle).
783- for (auto & memory : wasm.memories ) {
784- memory->module = memory->base = Name ();
784+
785+ if (!preserveImportsAndExports) {
786+ // Avoid an imported memory (which the fuzz harness would need to handle).
787+ for (auto & memory : wasm.memories ) {
788+ memory->module = memory->base = Name ();
789+ }
785790 }
786791}
787792
@@ -826,8 +831,11 @@ void TranslateToFuzzReader::finalizeTable() {
826831 assert (ReasonableMaxTableSize <= Table::kMaxSize );
827832
828833 table->max = oneIn (2 ) ? Address (Table::kUnlimitedSize ) : table->initial ;
829- // Avoid an imported table (which the fuzz harness would need to handle).
830- table->module = table->base = Name ();
834+
835+ if (!preserveImportsAndExports) {
836+ // Avoid an imported table (which the fuzz harness would need to handle).
837+ table->module = table->base = Name ();
838+ }
831839 }
832840}
833841
@@ -841,8 +849,9 @@ void TranslateToFuzzReader::shuffleExports() {
841849 // we emit invokes for a function right after it (so we end up calling the
842850 // same code several times in succession, but interleaving it with others may
843851 // find more things). But we also keep a good chance for the natural order
844- // here, as it may help some initial content.
845- if (wasm.exports .empty () || oneIn (2 )) {
852+ // here, as it may help some initial content. Note we cannot do this if we are
853+ // preserving the exports, as their order is something we must maintain.
854+ if (wasm.exports .empty () || preserveImportsAndExports || oneIn (2 )) {
846855 return ;
847856 }
848857
@@ -881,14 +890,24 @@ void TranslateToFuzzReader::addImportLoggingSupport() {
881890 Name baseName = std::string (" log-" ) + type.toString ();
882891 func->name = Names::getValidFunctionName (wasm, baseName);
883892 logImportNames[type] = func->name ;
884- func->module = " fuzzing-support" ;
885- func->base = baseName;
893+ if (!preserveImportsAndExports) {
894+ func->module = " fuzzing-support" ;
895+ func->base = baseName;
896+ } else {
897+ // We cannot add an import, so just make it a trivial function (this is
898+ // simpler than avoiding calls to logging in all the rest of the logic).
899+ func->body = builder.makeNop ();
900+ }
886901 func->type = Signature (type, Type::none);
887902 wasm.addFunction (std::move (func));
888903 }
889904}
890905
891906void TranslateToFuzzReader::addImportCallingSupport () {
907+ if (preserveImportsAndExports) {
908+ return ;
909+ }
910+
892911 if (wasm.features .hasReferenceTypes () && closedWorld) {
893912 // In closed world mode we must *remove* the call-ref* imports, if they
894913 // exist in the initial content. These are not valid to call in closed-world
@@ -983,8 +1002,13 @@ void TranslateToFuzzReader::addImportThrowingSupport() {
9831002 throwImportName = Names::getValidFunctionName (wasm, " throw" );
9841003 auto func = std::make_unique<Function>();
9851004 func->name = throwImportName;
986- func->module = " fuzzing-support" ;
987- func->base = " throw" ;
1005+ if (!preserveImportsAndExports) {
1006+ func->module = " fuzzing-support" ;
1007+ func->base = " throw" ;
1008+ } else {
1009+ // As with logging, implement in a trivial way when we cannot add imports.
1010+ func->body = builder.makeNop ();
1011+ }
9881012 func->type = Signature (Type::i32 , Type::none);
9891013 wasm.addFunction (std::move (func));
9901014}
@@ -999,8 +1023,9 @@ void TranslateToFuzzReader::addImportTableSupport() {
9991023 }
10001024
10011025 // If a "table" export already exists, skip fuzzing these imports, as the
1002- // current export may not contain a valid table for it.
1003- if (wasm.getExportOrNull (" table" )) {
1026+ // current export may not contain a valid table for it. We also skip if we are
1027+ // not adding imports or exports.
1028+ if (wasm.getExportOrNull (" table" ) || preserveImportsAndExports) {
10041029 return ;
10051030 }
10061031
@@ -1033,8 +1058,9 @@ void TranslateToFuzzReader::addImportTableSupport() {
10331058}
10341059
10351060void TranslateToFuzzReader::addImportSleepSupport () {
1036- if (!oneIn (4 )) {
1037- // Fuzz this somewhat rarely, as it may be slow.
1061+ // Fuzz this somewhat rarely, as it may be slow, and only when we can add
1062+ // imports.
1063+ if (preserveImportsAndExports || !oneIn (4 )) {
10381064 return ;
10391065 }
10401066
@@ -1087,12 +1113,15 @@ void TranslateToFuzzReader::addHashMemorySupport() {
10871113 auto * body = builder.makeBlock (contents);
10881114 auto * hasher = wasm.addFunction (builder.makeFunction (
10891115 " hashMemory" , Signature (Type::none, Type::i32 ), {Type::i32 }, body));
1090- wasm.addExport (
1091- builder.makeExport (hasher->name , hasher->name , ExternalKind::Function));
1092- // Export memory so JS fuzzing can use it
1093- if (!wasm.getExportOrNull (" memory" )) {
1094- wasm.addExport (builder.makeExport (
1095- " memory" , wasm.memories [0 ]->name , ExternalKind::Memory));
1116+
1117+ if (!preserveImportsAndExports) {
1118+ wasm.addExport (
1119+ builder.makeExport (hasher->name , hasher->name , ExternalKind::Function));
1120+ // Export memory so JS fuzzing can use it
1121+ if (!wasm.getExportOrNull (" memory" )) {
1122+ wasm.addExport (builder.makeExport (
1123+ " memory" , wasm.memories [0 ]->name , ExternalKind::Memory));
1124+ }
10961125 }
10971126}
10981127
@@ -1340,7 +1369,7 @@ Function* TranslateToFuzzReader::addFunction() {
13401369 return t.isDefaultable ();
13411370 });
13421371 if (validExportParams && (numAddedFunctions == 0 || oneIn (2 )) &&
1343- !wasm.getExportOrNull (func->name )) {
1372+ !wasm.getExportOrNull (func->name ) && !preserveImportsAndExports ) {
13441373 auto * export_ = new Export;
13451374 export_->name = func->name ;
13461375 export_->value = func->name ;
@@ -1805,8 +1834,10 @@ void TranslateToFuzzReader::modifyInitialFunctions() {
18051834 for (Index i = 0 ; i < wasm.functions .size (); i++) {
18061835 auto * func = wasm.functions [i].get ();
18071836 // We can't allow extra imports, as the fuzzing infrastructure wouldn't
1808- // know what to provide. Keep only our own fuzzer imports.
1809- if (func->imported () && func->module == " fuzzing-support" ) {
1837+ // know what to provide. Keep only our own fuzzer imports (or, if we are
1838+ // preserving imports, keep them all).
1839+ if (func->imported () &&
1840+ (func->module == " fuzzing-support" || preserveImportsAndExports)) {
18101841 continue ;
18111842 }
18121843 FunctionCreationContext context (*this , func);
@@ -1907,7 +1938,12 @@ void TranslateToFuzzReader::addInvocations(Function* func) {
19071938 }
19081939 body->list .set (invocations);
19091940 wasm.addFunction (std::move (invoker));
1910- wasm.addExport (builder.makeExport (name, name, ExternalKind::Function));
1941+
1942+ // Most of the benefit of invocations is lost when we do not add exports for
1943+ // them, but still, they might be called by existing functions.
1944+ if (!preserveImportsAndExports) {
1945+ wasm.addExport (builder.makeExport (name, name, ExternalKind::Function));
1946+ }
19111947}
19121948
19131949Expression* TranslateToFuzzReader::make (Type type) {
0 commit comments