@@ -614,10 +614,12 @@ void TranslateToFuzzReader::setupGlobals() {
614
614
// run the wasm.
615
615
for (auto & global : wasm.globals ) {
616
616
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
+ }
621
623
} else {
622
624
// If the initialization referred to an imported global, it no longer can
623
625
// point to the same global after we make it a non-imported global unless
@@ -695,7 +697,7 @@ void TranslateToFuzzReader::setupTags() {
695
697
// As in modifyInitialFunctions(), we can't allow arbitrary tag imports, which
696
698
// would trap when the fuzzing infrastructure doesn't know what to provide.
697
699
for (auto & tag : wasm.tags ) {
698
- if (tag->imported ()) {
700
+ if (tag->imported () && !preserveImportsAndExports ) {
699
701
tag->module = tag->base = Name ();
700
702
}
701
703
}
@@ -707,7 +709,7 @@ void TranslateToFuzzReader::setupTags() {
707
709
}
708
710
709
711
// Add the fuzzing support tags manually sometimes.
710
- if (oneIn (2 )) {
712
+ if (!preserveImportsAndExports && oneIn (2 )) {
711
713
auto wasmTag = builder.makeTag (Names::getValidTagName (wasm, " wasmtag" ),
712
714
Signature (Type::i32 , Type::none));
713
715
wasmTag->module = " fuzzing-support" ;
@@ -779,9 +781,12 @@ void TranslateToFuzzReader::finalizeMemory() {
779
781
memory->max =
780
782
std::min (Address (memory->initial + 1 ), Address (Memory::kMaxSize32 ));
781
783
}
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
+ }
785
790
}
786
791
}
787
792
@@ -826,8 +831,11 @@ void TranslateToFuzzReader::finalizeTable() {
826
831
assert (ReasonableMaxTableSize <= Table::kMaxSize );
827
832
828
833
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
+ }
831
839
}
832
840
}
833
841
@@ -841,8 +849,9 @@ void TranslateToFuzzReader::shuffleExports() {
841
849
// we emit invokes for a function right after it (so we end up calling the
842
850
// same code several times in succession, but interleaving it with others may
843
851
// 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 )) {
846
855
return ;
847
856
}
848
857
@@ -881,14 +890,24 @@ void TranslateToFuzzReader::addImportLoggingSupport() {
881
890
Name baseName = std::string (" log-" ) + type.toString ();
882
891
func->name = Names::getValidFunctionName (wasm, baseName);
883
892
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
+ }
886
901
func->type = Signature (type, Type::none);
887
902
wasm.addFunction (std::move (func));
888
903
}
889
904
}
890
905
891
906
void TranslateToFuzzReader::addImportCallingSupport () {
907
+ if (preserveImportsAndExports) {
908
+ return ;
909
+ }
910
+
892
911
if (wasm.features .hasReferenceTypes () && closedWorld) {
893
912
// In closed world mode we must *remove* the call-ref* imports, if they
894
913
// exist in the initial content. These are not valid to call in closed-world
@@ -983,8 +1002,13 @@ void TranslateToFuzzReader::addImportThrowingSupport() {
983
1002
throwImportName = Names::getValidFunctionName (wasm, " throw" );
984
1003
auto func = std::make_unique<Function>();
985
1004
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
+ }
988
1012
func->type = Signature (Type::i32 , Type::none);
989
1013
wasm.addFunction (std::move (func));
990
1014
}
@@ -999,8 +1023,9 @@ void TranslateToFuzzReader::addImportTableSupport() {
999
1023
}
1000
1024
1001
1025
// 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) {
1004
1029
return ;
1005
1030
}
1006
1031
@@ -1033,8 +1058,9 @@ void TranslateToFuzzReader::addImportTableSupport() {
1033
1058
}
1034
1059
1035
1060
void 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 )) {
1038
1064
return ;
1039
1065
}
1040
1066
@@ -1087,12 +1113,15 @@ void TranslateToFuzzReader::addHashMemorySupport() {
1087
1113
auto * body = builder.makeBlock (contents);
1088
1114
auto * hasher = wasm.addFunction (builder.makeFunction (
1089
1115
" 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
+ }
1096
1125
}
1097
1126
}
1098
1127
@@ -1340,7 +1369,7 @@ Function* TranslateToFuzzReader::addFunction() {
1340
1369
return t.isDefaultable ();
1341
1370
});
1342
1371
if (validExportParams && (numAddedFunctions == 0 || oneIn (2 )) &&
1343
- !wasm.getExportOrNull (func->name )) {
1372
+ !wasm.getExportOrNull (func->name ) && !preserveImportsAndExports ) {
1344
1373
auto * export_ = new Export;
1345
1374
export_->name = func->name ;
1346
1375
export_->value = func->name ;
@@ -1805,8 +1834,10 @@ void TranslateToFuzzReader::modifyInitialFunctions() {
1805
1834
for (Index i = 0 ; i < wasm.functions .size (); i++) {
1806
1835
auto * func = wasm.functions [i].get ();
1807
1836
// 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)) {
1810
1841
continue ;
1811
1842
}
1812
1843
FunctionCreationContext context (*this , func);
@@ -1907,7 +1938,12 @@ void TranslateToFuzzReader::addInvocations(Function* func) {
1907
1938
}
1908
1939
body->list .set (invocations);
1909
1940
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
+ }
1911
1947
}
1912
1948
1913
1949
Expression* TranslateToFuzzReader::make (Type type) {
0 commit comments