summaryrefslogtreecommitdiff
path: root/scripts/fuzz_shell.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/fuzz_shell.js')
-rw-r--r--scripts/fuzz_shell.js75
1 files changed, 68 insertions, 7 deletions
diff --git a/scripts/fuzz_shell.js b/scripts/fuzz_shell.js
index 72120cf7f..d9a994896 100644
--- a/scripts/fuzz_shell.js
+++ b/scripts/fuzz_shell.js
@@ -134,6 +134,29 @@ function logValue(x, y) {
console.log('[LoggingExternalInterface logging ' + printed(x, y) + ']');
}
+// Some imports need to access exports by index.
+var exportsList;
+function getExportByIndex(index) {
+ if (!exportsList) {
+ exportsList = [];
+ for (var e in exports) {
+ exportsList.push(e);
+ }
+ }
+ return exports[exportsList[index]];
+}
+
+// Given a wasm function, call it as best we can from JS, and return the result.
+function callFunc(func) {
+ // Send the function a null for each parameter. Null can be converted without
+ // error to both a number and a reference.
+ var args = [];
+ for (var i = 0; i < func.length; i++) {
+ args.push(null);
+ }
+ return func.apply(null, args);
+}
+
// Table get/set operations need a BigInt if the table has 64-bit indexes. This
// adds a proper cast as needed.
function toAddressType(table, index) {
@@ -172,6 +195,50 @@ var imports = {
'table-set': (index, value) => {
exports.table.set(toAddressType(exports.table, index), value);
},
+
+ // Export operations.
+ 'call-export': (index) => {
+ callFunc(getExportByIndex(index));
+ },
+ 'call-export-catch': (index) => {
+ try {
+ callFunc(getExportByIndex(index));
+ return 0;
+ } catch (e) {
+ // We only want to catch exceptions, not wasm traps: traps should still
+ // halt execution. Handling this requires different code in wasm2js, so
+ // check for that first (wasm2js does not define RuntimeError, so use
+ // that for the check - when wasm2js is run, we override the entire
+ // WebAssembly object with a polyfill, so we know exactly what it
+ // contains).
+ var wasm2js = !WebAssembly.RuntimeError;
+ if (!wasm2js) {
+ // When running native wasm, we can detect wasm traps.
+ if (e instanceof WebAssembly.RuntimeError) {
+ throw e;
+ }
+ }
+ var text = e + '';
+ // We must not swallow host limitations here: a host limitation is a
+ // problem that means we must not compare the outcome here to any other
+ // VM.
+ var hostIssues = ['requested new array is too large',
+ 'out of memory',
+ 'Maximum call stack size exceeded'];
+ if (wasm2js) {
+ // When wasm2js does trap, it just throws an "abort" error.
+ hostIssues.push('abort');
+ }
+ for (var hostIssue of hostIssues) {
+ if (text.includes(hostIssue)) {
+ throw e;
+ }
+ }
+ // Otherwise, this is a normal exception we want to catch (a wasm
+ // exception, or a conversion error on the wasm/JS boundary, etc.).
+ return 1;
+ }
+ },
},
// Emscripten support.
'env': {
@@ -250,16 +317,10 @@ for (var e of exportsToCall) {
if (typeof exports[e] !== 'function') {
continue;
}
- // Send the function a null for each parameter. Null can be converted without
- // error to both a number and a reference.
var func = exports[e];
- var args = [];
- for (var i = 0; i < func.length; i++) {
- args.push(null);
- }
try {
console.log('[fuzz-exec] calling ' + e);
- var result = func.apply(null, args);
+ var result = callFunc(func);
if (typeof result !== 'undefined') {
console.log('[fuzz-exec] note result: ' + e + ' => ' + printed(result));
}