tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

binary.js (21756B)


      1 load(libdir + "wasm-binary.js");
      2 
      3 const { extractStackFrameFunction } = WasmHelpers;
      4 
      5 const { Module, RuntimeError, CompileError } = WebAssembly;
      6 
      7 const magicError = /failed to match magic number/;
      8 const unknownSection = /expected custom section/;
      9 
     10 function sectionError(section) {
     11    return RegExp(`failed to start ${section} section`);
     12 }
     13 
     14 function versionError(actual) {
     15    var expect = encodingVersion;
     16    var str = `binary version 0x${actual.toString(16)} does not match expected version 0x${expect.toString(16)}`;
     17    return RegExp(str);
     18 }
     19 
     20 const U32MAX_LEB = [255, 255, 255, 255, 15];
     21 
     22 const wasmEval = (code, imports) => new WebAssembly.Instance(new Module(code), imports).exports;
     23 
     24 assertErrorMessage(() => wasmEval(toU8([])), CompileError, magicError);
     25 assertErrorMessage(() => wasmEval(toU8([42])), CompileError, magicError);
     26 assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2])), CompileError, magicError);
     27 assertErrorMessage(() => wasmEval(toU8([1,2,3,4])), CompileError, magicError);
     28 assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3])), CompileError, versionError(0x6d736100));
     29 assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, 1])), CompileError, versionError(0x6d736100));
     30 assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, ver0])), CompileError, versionError(0x6d736100));
     31 assertErrorMessage(() => wasmEval(toU8([magic0, magic1, magic2, magic3, ver0, ver1, ver2])), CompileError, versionError(0x6d736100));
     32 
     33 var o = wasmEval(toU8(moduleHeaderThen()));
     34 assertEq(Object.getOwnPropertyNames(o).length, 0);
     35 
     36 // shared array buffer is not supported as a buffer source for compilation
     37 if (globalThis.SharedArrayBuffer) {
     38  assertErrorMessage(() => wasmEval(toSharedU8(moduleHeaderThen())), TypeError, /first argument must be an ArrayBuffer/);
     39 }
     40 
     41 // unfinished known sections
     42 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(typeId))), CompileError, sectionError("type"));
     43 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(importId))), CompileError, sectionError("import"));
     44 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(functionId))), CompileError, sectionError("function"));
     45 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(tableId))), CompileError, sectionError("table"));
     46 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(memoryId))), CompileError, sectionError("memory"));
     47 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(globalId))), CompileError, sectionError("global"));
     48 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(exportId))), CompileError, sectionError("export"));
     49 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(startId))), CompileError, sectionError("start"));
     50 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(elemId))), CompileError, sectionError("elem"));
     51 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(codeId))), CompileError, sectionError("code"));
     52 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(dataId))), CompileError, sectionError("data"));
     53 
     54 // unknown sections are unconditionally rejected
     55 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37))), CompileError, unknownSection);
     56 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37, 0))), CompileError, unknownSection);
     57 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(37, 1, 0))), CompileError, unknownSection);
     58 
     59 // user sections have special rules
     60 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0))), CompileError, sectionError("custom"));  // no length
     61 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 0))), CompileError, sectionError("custom"));  // no id
     62 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 0, 0))), CompileError, sectionError("custom"));  // payload too small to have id length
     63 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 1))), CompileError, sectionError("custom"));  // id not present
     64 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 1, 65))), CompileError, sectionError("custom"));  // id length doesn't fit in section
     65 assertErrorMessage(() => wasmEval(toU8(moduleHeaderThen(0, 1, 0, 0))), CompileError, sectionError("custom"));  // second, unfinished custom section
     66 wasmEval(toU8(moduleHeaderThen(0, 1, 0)));  // empty id
     67 wasmEval(toU8(moduleHeaderThen(0, 1, 0,  0, 1, 0)));  // 2x empty id
     68 wasmEval(toU8(moduleHeaderThen(0, 2, 1, 65)));  // id = "A"
     69 
     70 const v2vSig = {args:[], ret:VoidCode};
     71 const v2vSigSection = sigSection([v2vSig]);
     72 const i2vSig = {args:[I32Code], ret:VoidCode};
     73 const v2vBody = funcBody({locals:[], body:[]});
     74 
     75 assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: U32MAX_LEB } ])), CompileError, /too many types/);
     76 assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1, 0], } ])), CompileError, /expected type form/);
     77 assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1, FuncCode, ...U32MAX_LEB], } ])), CompileError, /too many arguments in signature/);
     78 
     79 assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: typeId, body: [1]}])), CompileError);
     80 assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: typeId, body: [1, 1, 0]}])), CompileError);
     81 
     82 wasmEval(moduleWithSections([sigSection([])]));
     83 wasmEval(moduleWithSections([v2vSigSection]));
     84 wasmEval(moduleWithSections([sigSection([i2vSig])]));
     85 wasmEval(moduleWithSections([sigSection([v2vSig, i2vSig])]));
     86 
     87 assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[], ret:33}])])), CompileError, /bad type/);
     88 assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([{args:[33], ret:VoidCode}])])), CompileError, /bad type/);
     89 
     90 assertThrowsInstanceOf(() => wasmEval(moduleWithSections([sigSection([]), declSection([0])])), CompileError, /signature index out of range/);
     91 assertThrowsInstanceOf(() => wasmEval(moduleWithSections([v2vSigSection, declSection([1])])), CompileError, /signature index out of range/);
     92 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0])])), CompileError, /expected code section/);
     93 wasmEval(moduleWithSections([v2vSigSection, declSection([0]), bodySection([v2vBody])]));
     94 
     95 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0]), bodySection([v2vBody.concat(v2vBody)])])), CompileError, /byte size mismatch in code section/);
     96 
     97 assertThrowsInstanceOf(() => wasmEval(moduleWithSections([v2vSigSection, {name: importId, body:[]}])), CompileError);
     98 assertErrorMessage(() => wasmEval(moduleWithSections([importSection([{module:"a", item:"b", funcTypeIndex:0}])])), CompileError, /signature index out of range/);
     99 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, importSection([{module:"a", item:"b", funcTypeIndex:1}])])), CompileError, /signature index out of range/);
    100 wasmEval(moduleWithSections([v2vSigSection, importSection([])]));
    101 wasmEval(moduleWithSections([v2vSigSection, importSection([{module:"a", item:"", funcTypeIndex:0}])]), {a:{"":()=>{}}});
    102 
    103 wasmEval(moduleWithSections([
    104    v2vSigSection,
    105    importSection([{module:"a", item:"", funcTypeIndex:0}]),
    106    declSection([0]),
    107    bodySection([v2vBody])
    108 ]), {a:{"":()=>{}}});
    109 
    110 assertErrorMessage(() => wasmEval(moduleWithSections([ dataSection([{offset:1, elems:[]}]) ])), CompileError, /data segment requires a memory section/);
    111 
    112 wasmEval(moduleWithSections([defaultTableSection(0)]));
    113 wasmEval(moduleWithSections([elemSection([])]));
    114 wasmEval(moduleWithSections([defaultTableSection(0), elemSection([])]));
    115 wasmEval(moduleWithSections([defaultTableSection(1), elemSection([{offset:1, elems:[]}])]));
    116 assertErrorMessage(() => wasmEval(moduleWithSections([defaultTableSection(1), elemSection([{offset:0, elems:[0]}])])), CompileError, /element index out of range/);
    117 wasmEval(moduleWithSections([v2vSigSection, declSection([0]), defaultTableSection(1), elemSection([{offset:0, elems:[0]}]), bodySection([v2vBody])]));
    118 wasmEval(moduleWithSections([v2vSigSection, declSection([0]), defaultTableSection(2), elemSection([{offset:0, elems:[0,0]}]), bodySection([v2vBody])]));
    119 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0]), defaultTableSection(2), elemSection([{offset:0, elems:[0,1]}]), bodySection([v2vBody])])), CompileError, /element index out of range/);
    120 wasmEval(moduleWithSections([v2vSigSection, declSection([0,0,0]), defaultTableSection(4), elemSection([{offset:0, elems:[0,1,0,2]}]), bodySection([v2vBody, v2vBody, v2vBody])]));
    121 wasmEval(moduleWithSections([sigSection([v2vSig,i2vSig]), declSection([0,0,1]), defaultTableSection(3), elemSection([{offset:0,elems:[0,1,2]}]), bodySection([v2vBody, v2vBody, v2vBody])]));
    122 
    123 wasmEval(moduleWithSections([tableSection0()]));
    124 
    125 wasmEval(moduleWithSections([memorySection(0)]));
    126 
    127 function memorySection2() {
    128    var body = [];
    129    body.push(...varU32(2));           // number of memories
    130    body.push(...varU32(0x0));
    131    body.push(...varU32(0));
    132    body.push(...varU32(0x0));
    133    body.push(...varU32(0));
    134    return { name: memoryId, body };
    135 }
    136 
    137 wasmEval(moduleWithSections([memorySection0()]));
    138 wasmEval(moduleWithSections([memorySection2()]));
    139 
    140 // Test early 'end'
    141 const bodyMismatch = /(function body length mismatch)|(operators remaining after end of function)/;
    142 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[EndCode]})])])), CompileError, bodyMismatch);
    143 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[UnreachableCode,EndCode]})])])), CompileError, bodyMismatch);
    144 assertErrorMessage(() => wasmEval(moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[EndCode,UnreachableCode]})])])), CompileError, bodyMismatch);
    145 
    146 // Ignore errors in name section.
    147 var tooBigNameSection = {
    148    name: userDefinedId,
    149    body: [...string(nameName), ...varU32(Math.pow(2, 31))] // declare 2**31 functions.
    150 };
    151 wasmEval(moduleWithSections([tooBigNameSection]));
    152 
    153 // Custom sections must have valid UTF-8 names
    154 assertErrorMessage(() => wasmEval(toU8([0,97,115,109,1,0,0,0,0,3,2,254,255,])), CompileError, /failed to start custom section/);
    155 
    156 // Skip custom sections before any expected section
    157 var customDefSec = customSection("wee", 42, 13);
    158 var declSec = declSection([0]);
    159 var bodySec = bodySection([v2vBody]);
    160 var nameSec = nameSection([funcNameSubsection([{name:'hi'}])]);
    161 wasmEval(moduleWithSections([customDefSec, v2vSigSection, declSec, bodySec]));
    162 wasmEval(moduleWithSections([v2vSigSection, customDefSec, declSec, bodySec]));
    163 wasmEval(moduleWithSections([v2vSigSection, declSec, customDefSec, bodySec]));
    164 wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, customDefSec]));
    165 wasmEval(moduleWithSections([customDefSec, customDefSec, v2vSigSection, declSec, bodySec]));
    166 wasmEval(moduleWithSections([customDefSec, customDefSec, v2vSigSection, customDefSec, declSec, customDefSec, bodySec]));
    167 
    168 // custom sections reflection:
    169 function checkCustomSection(buf, val) {
    170    assertEq(buf instanceof ArrayBuffer, true);
    171    assertEq(buf.byteLength, 1);
    172    assertEq(new Uint8Array(buf)[0], val);
    173 }
    174 var custom1 = customSection("one", 1);
    175 var custom2 = customSection("one", 2);
    176 var custom3 = customSection("two", 3);
    177 var custom4 = customSection("three", 4);
    178 var custom5 = customSection("three", 5);
    179 var custom6 = customSection("three", 6);
    180 var m = new Module(moduleWithSections([custom1, v2vSigSection, custom2, declSec, custom3, bodySec, custom4, nameSec, custom5, custom6]));
    181 var arr = Module.customSections(m, "one");
    182 assertEq(arr.length, 2);
    183 checkCustomSection(arr[0], 1);
    184 checkCustomSection(arr[1], 2);
    185 var arr = Module.customSections(m, "two");
    186 assertEq(arr.length, 1);
    187 checkCustomSection(arr[0], 3);
    188 var arr = Module.customSections(m, "three");
    189 assertEq(arr.length, 3);
    190 checkCustomSection(arr[0], 4);
    191 checkCustomSection(arr[1], 5);
    192 checkCustomSection(arr[2], 6);
    193 var arr = Module.customSections(m, "name");
    194 assertEq(arr.length, 1);
    195 assertEq(arr[0].byteLength, nameSec.body.length - 5 /* 4name */);
    196 
    197 // Test name/custom section warnings:
    198 const nameWarning = /validated with warning.*'name' custom section/;
    199 const okNameSec = nameSection([]);
    200 assertNoWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, okNameSec])));
    201 const badNameSec1 = nameSection([]);
    202 badNameSec1.body.push(1);
    203 assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec1])), nameWarning);
    204 const badNameSec2 = nameSection([funcNameSubsection([{name:'blah'}])]);
    205 badNameSec2.body.push(100, 20, 42, 83);
    206 assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec2])), nameWarning);
    207 const badNameSec3 = nameSection([funcNameSubsection([{name:'blah'}])]);
    208 badNameSec3.body.pop();
    209 assertWarning(() => wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, badNameSec3])), nameWarning);
    210 assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi')])])));
    211 assertWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi'), moduleNameSubsection('boo')])])), nameWarning);
    212 // Unknown name subsection
    213 assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi'), [4, 0]])])));
    214 assertWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi'), [4, 1]])])), nameWarning);
    215 assertNoWarning(() => wasmEval(moduleWithSections([nameSection([moduleNameSubsection('hi'), [4, 1, 42]])])));
    216 
    217 // Provide a module name but no function names.
    218 assertErrorMessage(() => wasmEval(moduleWithSections([
    219    v2vSigSection,
    220    declSection([0]),
    221    exportSection([{funcIndex: 0, name: "f"}]),
    222    bodySection([funcBody({locals:[], body:[UnreachableCode]})]),
    223    nameSection([moduleNameSubsection('hi')])])
    224 ).f(), RuntimeError, /unreachable/);
    225 
    226 // Diagnose invalid block signature types.
    227 for (var bad of [0xff, 1, 0x3f])
    228    assertErrorMessage(() => wasmEval(moduleWithSections([sigSection([v2vSig]), declSection([0]), bodySection([funcBody({locals:[], body:[BlockCode, bad, EndCode]})])])), CompileError, /(invalid .*block type)|(unknown type)/);
    229 
    230 const multiValueModule = moduleWithSections([sigSection([v2vSig]), declSection([0]), bodySection([funcBody({locals:[], body:[BlockCode, 0, EndCode]})])]);
    231 // In this test module, 0 denotes a void-to-void block type.
    232 assertEq(WebAssembly.validate(multiValueModule), true);
    233 
    234 // Ensure all invalid opcodes are rejected.  Note that the game here (and for
    235 // the prefixed cases below) is to present only opcodes which will be rejected by
    236 // *both* Baseline and Ion.
    237 for (let op of undefinedOpcodes) {
    238    let binary = moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[op]})])]);
    239    assertErrorMessage(() => wasmEval(binary), CompileError, /((unrecognized|Unknown) opcode)|(tail calls support is not enabled)|(Exceptions support is not enabled)|(Unexpected EOF)/);
    240    assertEq(WebAssembly.validate(binary), false);
    241 }
    242 
    243 // Prefixed opcodes
    244 
    245 function checkIllegalPrefixed(prefix, opcode) {
    246    let binary = moduleWithSections([v2vSigSection,
    247                                     declSection([0]),
    248                                     bodySection([funcBody({locals:[],
    249                                                            body:[prefix, ...varU32(opcode)]})])]);
    250    assertErrorMessage(() => wasmEval(binary), CompileError, /((unrecognized|Unknown) opcode)|(Unknown.*subopcode)|(Unexpected EOF)|(SIMD support is not enabled)|(invalid lane index)/);
    251    assertEq(WebAssembly.validate(binary), false);
    252 }
    253 
    254 // Illegal GcPrefix opcodes
    255 
    256 let reservedGc = {
    257    // Structure operations
    258    0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true,
    259    // Array operations
    260    0x06: true, 0x07: true, 0x08: true, 0x09: true, 0x0a: true, 0x0b: true,
    261    0x0c: true, 0x0d: true, 0x0e: true, 0x0f: true, 0x10: true, 0x11: true,
    262    0x12: true, 0x13: true,
    263    // Ref operations
    264    0x14: true, 0x15: true, 0x16: true, 0x17: true, 0x18: true, 0x19: true,
    265    0x1a: true, 0x1b: true,
    266    // i31 operations
    267    0x1c: true, 0x1d: true, 0x1e: true,
    268 };
    269 for (let i = 0; i < 256; i++) {
    270    if (reservedGc.hasOwnProperty(i)) {
    271        continue;
    272    }
    273    checkIllegalPrefixed(GcPrefix, i);
    274 }
    275 
    276 // Illegal ThreadPrefix opcodes
    277 //
    278 // June 2017 threads draft:
    279 //
    280 //  0x00 .. 0x03 are wait/wake/fence ops
    281 //  0x10 .. 0x4f are primitive atomic ops
    282 
    283 for (let i = 0x4; i < 0x10; i++)
    284    checkIllegalPrefixed(ThreadPrefix, i);
    285 
    286 for (let i = 0x4f; i < 0x100; i++)
    287    checkIllegalPrefixed(ThreadPrefix, i);
    288 
    289 // Illegal Misc opcodes
    290 
    291 var reservedMisc =
    292    { // Saturating conversions (standardized)
    293      0x00: true, 0x01: true, 0x02: true, 0x03: true, 0x04: true, 0x05: true, 0x06: true, 0x07: true,
    294      // Bulk memory (proposed)
    295      0x08: true, 0x09: true, 0x0a: true, 0x0b: true, 0x0c: true, 0x0d: true, 0x0e: true,
    296      // Table (proposed)
    297      0x0f: true, 0x10: true, 0x11: true, 0x12: true,
    298      // Structure operations (experimental, internal)
    299      0x50: true, 0x51: true, 0x52: true, 0x53: true };
    300 
    301 for (let i = 0; i < 256; i++) {
    302    if (reservedMisc.hasOwnProperty(i))
    303        continue;
    304    checkIllegalPrefixed(MiscPrefix, i);
    305 }
    306 
    307 // Illegal SIMD opcodes - the upper bound is actually very large, not much to be
    308 // done about that.
    309 
    310 if (!wasmSimdEnabled()) {
    311    for (let i = 0; i < 0x130; i++) {
    312        checkIllegalPrefixed(SimdPrefix, i);
    313    }
    314 } else {
    315    let reservedSimd = [
    316        0x9a, 0xa2, 0xa5, 0xa6, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xbb,
    317        0xc2, 0xc5, 0xc6, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, 0xe2, 0xee,
    318        0x115, 0x116, 0x117,
    319        0x118, 0x119, 0x11a, 0x11b, 0x11c, 0x11d, 0x11e, 0x11f,
    320        0x120, 0x121, 0x122, 0x123, 0x124, 0x125, 0x126, 0x127,
    321        0x128, 0x129, 0x12a, 0x12b, 0x12c, 0x12d, 0x12e, 0x12f,
    322    ];
    323    for (let i of reservedSimd) {
    324        checkIllegalPrefixed(SimdPrefix, i);
    325    }
    326 }
    327 
    328 // Illegal MozPrefix opcodes (all of them)
    329 for (let i = 0; i < 256; i++)
    330    checkIllegalPrefixed(MozPrefix, i);
    331 
    332 for (let prefix of [ThreadPrefix, MiscPrefix, SimdPrefix, MozPrefix]) {
    333    // Prefix without a subsequent opcode.  We must ask funcBody not to add an
    334    // End code after the prefix, so the body really is just the prefix byte.
    335    let binary = moduleWithSections([v2vSigSection, declSection([0]), bodySection([funcBody({locals:[], body:[prefix]}, /*withEndCode=*/false)])]);
    336    assertErrorMessage(() => wasmEval(binary), CompileError, /(unable to read opcode)|(Unexpected EOF)|(Unknown opcode)/);
    337    assertEq(WebAssembly.validate(binary), false);
    338 }
    339 
    340 // Checking stack trace.
    341 function runStackTraceTest(moduleName, funcNames, expectedName) {
    342    var sections = [
    343        sigSection([v2vSig]),
    344        importSection([{module:"env", item:"callback", funcTypeIndex:0}]),
    345        declSection([0]),
    346        exportSection([{funcIndex:1, name: "run"}]),
    347        bodySection([funcBody({locals: [], body: [CallCode, varU32(0)]})]),
    348        customSection("whoa"),
    349        customSection("wee", 42),
    350    ];
    351    if (moduleName || funcNames) {
    352        var subsections = [];
    353        if (moduleName)
    354            subsections.push(moduleNameSubsection(moduleName));
    355        if (funcNames)
    356            subsections.push(funcNameSubsection(funcNames));
    357        sections.push(nameSection(subsections));
    358    }
    359    sections.push(customSection("yay", 13));
    360 
    361    var result = "";
    362    var callback = () => {
    363        result = extractStackFrameFunction(new Error().stack.split('\n')[1]);
    364    };
    365    wasmEval(moduleWithSections(sections), {"env": { callback }}).run();
    366    assertEq(result, expectedName);
    367 };
    368 
    369 runStackTraceTest(null, null, 'wasm-function[1]');
    370 runStackTraceTest(null, [{name:'blah'}, {name:'test'}], 'test');
    371 runStackTraceTest(null, [{name:'test', index:1}], 'test');
    372 runStackTraceTest(null, [{name:'blah'}, {name:'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
    373 runStackTraceTest(null, [{name:'blah'}, {name:'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
    374 runStackTraceTest(null, [{name:'blah'}, {name:'test1'}], 'test1');
    375 runStackTraceTest(null, [{name:'blah'}, {name:'test☃'}], 'test☃');
    376 runStackTraceTest(null, [{name:'blah'}, {name:'te\xE0\xFF'}], 'te\xE0\xFF');
    377 runStackTraceTest(null, [{name:'blah'}], 'wasm-function[1]');
    378 runStackTraceTest(null, [], 'wasm-function[1]');
    379 runStackTraceTest("", [{name:'blah'}, {name:'test'}], 'test');
    380 runStackTraceTest("a", [{name:'blah'}, {name:'test'}], 'a.test');
    381 // Notice that invalid names section content shall not fail the parsing
    382 runStackTraceTest(null, [{name:'blah'}, {name:'test', index: 2}], 'wasm-function[1]'); // invalid index
    383 runStackTraceTest(null, [{name:'blah'}, {name:'test', index: 100000}], 'wasm-function[1]'); // invalid index
    384 runStackTraceTest(null, [{name:'blah'}, {name:'test', nameLen: 100}], 'wasm-function[1]'); // invalid name size
    385 runStackTraceTest(null, [{name:'blah'}, {name:''}], 'wasm-function[1]'); // empty name
    386 
    387 // Enable and disable Gecko profiling mode, to ensure all live instances
    388 // names won't make us crash.
    389 enableGeckoProfiling();
    390 disableGeckoProfiling();
    391 
    392 function testValidNameSectionWithProfiling() {
    393    enableGeckoProfiling();
    394    wasmEval(moduleWithSections([v2vSigSection, declSec, bodySec, nameSec]));
    395    disableGeckoProfiling();
    396 }
    397 testValidNameSectionWithProfiling();
    398 
    399 // Memory alignment can use non-minimal LEB128
    400 wasmEval(moduleWithSections([
    401    v2vSigSection,
    402    declSection([0]),
    403    memorySection(0),
    404    bodySection([
    405        funcBody({locals: [], body: [
    406            I32ConstCode, 0x00, // i32.const 0
    407            I32Load,
    408                0x81, 0x00, // alignment 1, non-minimal
    409                0x00, // offset 0
    410            DropCode,
    411        ]}),
    412    ]),
    413 ]));