| // wasm2js.js - enough of a polyfill for the WebAssembly object so that we can load | |
| // wasm2js code that way. Similar to the same file in emscripten, but tailored for | |
| // fuzzing purposes here. | |
| var WebAssembly = { | |
| Memory: function(opts) { | |
| return { | |
| buffer: new ArrayBuffer(opts['initial'] * 64 * 1024), | |
| }; | |
| }, | |
| Table: function(opts) { | |
| var ret = new Array(opts['initial']); | |
| ret.grow = function(by) { | |
| ret.push(null); | |
| }; | |
| ret.set = function(i, func) { | |
| ret[i] = func; | |
| }; | |
| ret.get = function(i) { | |
| return ret[i]; | |
| }; | |
| return ret; | |
| }, | |
| Module: function(binary) { | |
| // TODO: use the binary and info somehow - right now the wasm2js output is embedded in | |
| // the main JS | |
| return {}; | |
| }, | |
| Instance: function(module, info) { | |
| // TODO: use the module and info somehow - right now the wasm2js output is embedded in | |
| // the main JS | |
| var decodeBase64 = typeof atob === 'function' ? atob : function (input) { | |
| var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | |
| var output = ''; | |
| var chr1, chr2, chr3; | |
| var enc1, enc2, enc3, enc4; | |
| var i = 0; | |
| // remove all characters that are not A-Z, a-z, 0-9, +, /, or = | |
| input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); | |
| do { | |
| enc1 = keyStr.indexOf(input.charAt(i++)); | |
| enc2 = keyStr.indexOf(input.charAt(i++)); | |
| enc3 = keyStr.indexOf(input.charAt(i++)); | |
| enc4 = keyStr.indexOf(input.charAt(i++)); | |
| chr1 = (enc1 << 2) | (enc2 >> 4); | |
| chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |
| chr3 = ((enc3 & 3) << 6) | enc4; | |
| output = output + String.fromCharCode(chr1); | |
| if (enc3 !== 64) { | |
| output = output + String.fromCharCode(chr2); | |
| } | |
| if (enc4 !== 64) { | |
| output = output + String.fromCharCode(chr3); | |
| } | |
| } while (i < input.length); | |
| return output; | |
| }; | |
| var atob = decodeBase64; | |
| // Additional imports | |
| info['env']['__tempMemory__'] = 0; // risky! | |
| // This will be replaced by the actual wasm2js code. | |
| var exports = instantiate(info, wasmMemory); | |
| // Save the exports on the module object, so that | |
| // WebAssembly.Module.exports() works. Ideally we would do this in | |
| // WebAssembly.Module(), but we don't know the exports at that point - all | |
| // the actual work happens in Instance(), here. In practice this is enough | |
| // as calls to WebAssembly.Module.exports() from the fuzzer happen after | |
| // instantiation. | |
| module.exports = exports; | |
| return { | |
| 'exports': exports | |
| }; | |
| }, | |
| instantiate: function(binary, info) { | |
| return { | |
| then: function(ok, err) { | |
| ok({ | |
| 'instance': new WebAssembly.Instance(new WebAssembly.Module(binary, info)) | |
| }); | |
| } | |
| }; | |
| } | |
| }; | |
| // Add the exports() API on top of the Module constructor. | |
| WebAssembly.Module.exports = (module) => { | |
| var ret = []; | |
| for (var key in module.exports) { | |
| ret.push({ name: key }); | |
| } | |
| return ret; | |
| }; | |
| var tempRet0 = 0; | |
| var env = { | |
| log_i32: function(x) { | |
| console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ']'); | |
| }, | |
| log_i64: function(x, h) { | |
| console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ' ' + literal(h, 'i32') + ']'); | |
| }, | |
| log_f32: function(x) { | |
| console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']'); | |
| }, | |
| log_f64: function(x) { | |
| console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']'); | |
| }, | |
| log_execution: function(loc) { | |
| console.log('log_execution ' + loc); | |
| }, | |
| setTempRet0: function(x) { | |
| tempRet0 = x; | |
| }, | |
| getTempRet0: function() { | |
| return x; | |
| }, | |
| get_i32: function(loc, index, value) { | |
| console.log('get_i32 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| get_i64: function(loc, index, low, high) { | |
| console.log('get_i64 ' + [loc, index, low, high]); | |
| env['setTempRet0'](high); | |
| return low; | |
| }, | |
| get_f32: function(loc, index, value) { | |
| console.log('get_f32 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| get_f64: function(loc, index, value) { | |
| console.log('get_f64 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| set_i32: function(loc, index, value) { | |
| console.log('set_i32 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| set_i64: function(loc, index, low, high) { | |
| console.log('set_i64 ' + [loc, index, low, high]); | |
| env['setTempRet0'](high); | |
| return low; | |
| }, | |
| set_f32: function(loc, index, value) { | |
| console.log('set_f32 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| set_f64: function(loc, index, value) { | |
| console.log('set_f64 ' + [loc, index, value]); | |
| return value; | |
| }, | |
| load_ptr: function(loc, bytes, offset, ptr) { | |
| console.log('load_ptr ' + [loc, bytes, offset, ptr]); | |
| return ptr; | |
| }, | |
| load_val_i32: function(loc, value) { | |
| console.log('load_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| load_val_i64: function(loc, low, high) { | |
| console.log('load_val_i64 ' + [loc, low, high]); | |
| env['setTempRet0'](high); | |
| return low; | |
| }, | |
| load_val_f32: function(loc, value) { | |
| console.log('load_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| load_val_f64: function(loc, value) { | |
| console.log('load_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| store_ptr: function(loc, bytes, offset, ptr) { | |
| console.log('store_ptr ' + [loc, bytes, offset, ptr]); | |
| return ptr; | |
| }, | |
| store_val_i32: function(loc, value) { | |
| console.log('store_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| store_val_i64: function(loc, low, high) { | |
| console.log('store_val_i64 ' + [loc, low, high]); | |
| env['setTempRet0'](high); | |
| return low; | |
| }, | |
| store_val_f32: function(loc, value) { | |
| console.log('store_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| store_val_f64: function(loc, value) { | |
| console.log('store_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_get_val_i32: function(loc, value) { | |
| console.log('struct_get_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_get_val_i64: function(loc, value) { | |
| console.log('struct_get_val_i64 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_get_val_f32: function(loc, value) { | |
| console.log('struct_get_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_get_val_f64: function(loc, value) { | |
| console.log('struct_get_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_set_val_i32: function(loc, value) { | |
| console.log('struct_set_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_set_val_i64: function(loc, value) { | |
| console.log('struct_set_val_i64 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_set_val_f32: function(loc, value) { | |
| console.log('struct_set_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| struct_set_val_f64: function(loc, value) { | |
| console.log('struct_set_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_get_val_i32: function(loc, value) { | |
| console.log('array_get_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_get_val_i64: function(loc, value) { | |
| console.log('array_get_val_i64 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_get_val_f32: function(loc, value) { | |
| console.log('array_get_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_get_val_f64: function(loc, value) { | |
| console.log('array_get_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_set_val_i32: function(loc, value) { | |
| console.log('array_set_val_i32 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_set_val_i64: function(loc, value) { | |
| console.log('array_set_val_i64 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_set_val_f32: function(loc, value) { | |
| console.log('array_set_val_f32 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_set_val_f64: function(loc, value) { | |
| console.log('array_set_val_f64 ' + [loc, value]); | |
| return value; | |
| }, | |
| array_get_index: function(loc, value) { | |
| console.log('array_get_index ' + [loc, value]); | |
| return value; | |
| }, | |
| array_set_index: function(loc, value) { | |
| console.log('array_set_index ' + [loc, value]); | |
| return value; | |
| }, | |
| }; | |
| var wasmMemory = new WebAssembly.Memory({ initial: 1 }); |