tor-browser

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

limits.js (9506B)


      1 // Tests of limits of memory and table types
      2 
      3 const PageSize = PageSizeInBytes;
      4 const MemoryMaxValid = 65536;
      5 const MemoryMaxRuntime = MaxPagesIn32BitMemory;
      6 
      7 const TableMaxValid = 0xffff_ffff;
      8 const TableMaxRuntime = 10_000_000;
      9 
     10 // Test that a memory type is valid within a module
     11 function testMemoryValidate(initial, maximum, shared) {
     12  wasmValidateText(`(module
     13    (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
     14  )`);
     15 }
     16 
     17 testMemoryValidate(0, undefined, false);
     18 testMemoryValidate(1, undefined, false);
     19 testMemoryValidate(0, 1, false);
     20 testMemoryValidate(0, 1, true);
     21 testMemoryValidate(1, 1, false);
     22 testMemoryValidate(1, 1, true);
     23 testMemoryValidate(MemoryMaxValid, undefined, false);
     24 testMemoryValidate(MemoryMaxValid, MemoryMaxValid, false);
     25 testMemoryValidate(MemoryMaxValid, MemoryMaxValid, true);
     26 
     27 // Test that a memory type is not valid within a module
     28 function testMemoryFailValidate(initial, maximum, shared, pattern) {
     29  wasmFailValidateText(`(module
     30    (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
     31  )`, pattern);
     32 }
     33 
     34 testMemoryFailValidate(2, 1, false, /size minimum must not be greater than maximum/);
     35 testMemoryFailValidate(1, undefined, true, /maximum length required for shared memory/);
     36 testMemoryFailValidate(MemoryMaxValid + 1, undefined, false, /initial memory size too big/);
     37 testMemoryFailValidate(MemoryMaxValid, MemoryMaxValid + 1, false, /maximum memory size too big/);
     38 testMemoryFailValidate(MemoryMaxValid, MemoryMaxValid + 1, true, /maximum memory size too big/);
     39 
     40 // Test that a memory type is invalid for constructing a WebAssembly.Memory
     41 function testMemoryFailConstruct(initial, maximum, shared, pattern) {
     42  assertErrorMessage(() => new WebAssembly.Memory({
     43    initial,
     44    maximum,
     45    shared
     46  }), RangeError, pattern);
     47 }
     48 
     49 // Test initial length, giving a maximum only if required due to being shared
     50 testMemoryFailConstruct(MemoryMaxValid + 1, undefined, false, /bad Memory initial size/);
     51 testMemoryFailConstruct(MemoryMaxValid + 1, MemoryMaxValid + 1, true, /bad Memory initial size/);
     52 // Test maximum length
     53 testMemoryFailConstruct(0, MemoryMaxValid + 1, false, /bad Memory maximum size/);
     54 testMemoryFailConstruct(0, MemoryMaxValid + 1, true, /bad Memory maximum size/);
     55 
     56 // Test that a memory type can be instantiated within a module or constructed
     57 // with a WebAssembly.Memory
     58 function testMemoryCreate(initial, maximum, shared) {
     59  // May OOM, but must not fail to validate
     60  try {
     61      wasmEvalText(`(module
     62        (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
     63      )`);
     64  } catch (e) {
     65      assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
     66  }
     67  try {
     68    new WebAssembly.Memory({initial, maximum, shared});
     69  } catch (e) {
     70    assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
     71  }
     72 }
     73 
     74 testMemoryCreate(0, undefined, false);
     75 testMemoryCreate(1, undefined, false);
     76 testMemoryCreate(0, 1, false);
     77 testMemoryCreate(0, 1, true);
     78 testMemoryCreate(1, 1, false);
     79 testMemoryCreate(1, 1, true);
     80 testMemoryCreate(MemoryMaxRuntime, undefined, false);
     81 testMemoryCreate(MemoryMaxRuntime, MemoryMaxValid, false);
     82 testMemoryCreate(MemoryMaxRuntime, MemoryMaxValid, true);
     83 
     84 // Test that a memory type cannot be instantiated within a module or constructed
     85 // with a WebAssembly.Memory
     86 
     87 if (MemoryMaxRuntime < 65536) {
     88    let testMemoryFailCreate = function(initial, maximum, shared) {
     89        assertErrorMessage(() => wasmEvalText(`(module
     90    (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
     91  )`), WebAssembly.RuntimeError, /too many memory pages/);
     92        assertErrorMessage(() => new WebAssembly.Memory({
     93            initial,
     94            maximum,
     95            shared
     96        }), WebAssembly.RuntimeError, /too many memory pages/);
     97    }
     98 
     99    testMemoryFailCreate(MemoryMaxRuntime + 1, undefined, false);
    100    testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, false);
    101    testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, true);
    102 } else {
    103    let testMemoryFailCreate = function(initial, maximum, shared, jsError, jsMsg) {
    104        assertErrorMessage(() => wasmEvalText(`(module
    105    (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
    106  )`), WebAssembly.CompileError, /(initial memory size too big)|(memory size minimum must not be greater than maximum)/);
    107        assertErrorMessage(() => new WebAssembly.Memory({
    108            initial,
    109            maximum,
    110            shared
    111        }), jsError, jsMsg);
    112    }
    113 
    114    testMemoryFailCreate(MemoryMaxRuntime + 1, undefined, false, RangeError, /bad Memory initial size/);
    115    testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, false, RangeError, /initial Memory size cannot be greater than maximum/);
    116    testMemoryFailCreate(MemoryMaxRuntime + 1, MemoryMaxValid, true, RangeError, /initial Memory size cannot be greater than maximum/);
    117 }
    118 
    119 
    120 // Test that a memory type cannot be grown from initial to a target due to an
    121 // implementation limit
    122 function testMemoryFailGrow(initial, maximum, target, shared) {
    123  let {run} = wasmEvalText(`(module
    124    (memory ${initial} ${maximum || ''} ${shared ? 'shared' : ''})
    125    (func (export "run") (result i32)
    126      i32.const ${target - initial}
    127      memory.grow
    128    )
    129  )`).exports;
    130  assertEq(run(), -1, 'failed to grow');
    131 
    132  let mem = new WebAssembly.Memory({
    133    initial,
    134    maximum,
    135    shared
    136  });
    137  assertErrorMessage(() => mem.grow(target - initial), RangeError, /failed to grow memory/);
    138 }
    139 
    140 testMemoryFailGrow(1, undefined, MemoryMaxRuntime + 1, false);
    141 testMemoryFailGrow(1, MemoryMaxValid, MemoryMaxRuntime + 1, false);
    142 testMemoryFailGrow(1, MemoryMaxValid, MemoryMaxRuntime + 1, true);
    143 
    144 // Test that a table type is valid within a module
    145 function testTableValidate(initial, maximum) {
    146  wasmValidateText(`(module
    147    (table ${initial} ${maximum || ''} funcref)
    148  )`);
    149 }
    150 
    151 testTableValidate(0, undefined);
    152 testTableValidate(1, undefined);
    153 testTableValidate(0, 1);
    154 testTableValidate(1, 1);
    155 testTableValidate(TableMaxValid, undefined);
    156 testTableValidate(TableMaxValid, TableMaxValid);
    157 
    158 // Test that a table type is not valid within a module
    159 function testTableFailValidate(initial, maximum, pattern) {
    160  wasmFailValidateText(`(module
    161    (table ${initial} ${maximum || ''} funcref)
    162  )`, pattern);
    163 }
    164 
    165 testTableFailValidate(2, 1, /size minimum must not be greater than maximum/);
    166 // The maximum valid table value is equivalent to the maximum encodable limit
    167 // value, so we cannot test too large of a table limit in a module.
    168 assertEq(TableMaxValid + 1 > 0xffffffff, true);
    169 
    170 // Test that a table type is invalid for constructing a WebAssembly.Table
    171 function testTableFailConstruct(initial, maximum, pattern) {
    172  assertErrorMessage(() => new WebAssembly.Table({
    173    initial,
    174    maximum,
    175    element: 'funcref',
    176  }), TypeError, pattern);
    177 }
    178 
    179 testTableFailConstruct(TableMaxValid + 1, undefined, /bad Table initial size/);
    180 testTableFailConstruct(0, TableMaxValid + 1, /bad Table maximum size/);
    181 
    182 // Test that a table type can be instantiated within a module or constructed
    183 // with a WebAssembly.Table
    184 function testTableCreate(initial, maximum) {
    185  // May OOM, but must not fail to validate
    186  try {
    187      wasmEvalText(`(module
    188        (table ${initial} ${maximum || ''} funcref)
    189      )`);
    190  } catch (e) {
    191      assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
    192  }
    193  try {
    194    new WebAssembly.Table({
    195      initial,
    196      maximum,
    197      element: 'funcref',
    198    });
    199  } catch (e) {
    200    assertEq(String(e).indexOf("out of memory") !== -1, true, `${e}`);
    201  }
    202 }
    203 
    204 testTableCreate(0, undefined);
    205 testTableCreate(1, undefined);
    206 testTableCreate(0, 1);
    207 testTableCreate(1, 1);
    208 testTableCreate(TableMaxRuntime, undefined);
    209 testTableCreate(TableMaxRuntime, TableMaxValid);
    210 
    211 // Test that a table type cannot be instantiated within a module or constructed
    212 // with a WebAssembly.Table
    213 function testTableFailCreate(initial, maximum, pattern) {
    214  assertErrorMessage(() => wasmEvalText(`(module
    215    (table ${initial} ${maximum || ''} funcref)
    216  )`), WebAssembly.RuntimeError, pattern);
    217  assertErrorMessage(() => new WebAssembly.Table({
    218    initial,
    219    maximum,
    220    element: 'funcref',
    221  }), WebAssembly.RuntimeError, pattern);
    222 }
    223 
    224 testTableFailCreate(TableMaxRuntime + 1, undefined, /too many table elements/);
    225 testTableFailCreate(TableMaxRuntime + 1, TableMaxValid, /too many table elements/);
    226 
    227 // Test that a table type cannot be grown from initial to a target due to an
    228 // implementation limit
    229 function testTableFailGrow(initial, maximum, target) {
    230  let {run} = wasmEvalText(`(module
    231    (table ${initial} ${maximum || ''} externref)
    232    (func (export "run") (result i32)
    233      ref.null extern
    234      i32.const ${target - initial}
    235      table.grow
    236    )
    237  )`).exports;
    238  assertEq(run(), -1, 'failed to grow');
    239 
    240  let tab = new WebAssembly.Table({
    241    initial,
    242    maximum,
    243    element: 'externref',
    244  });
    245  assertErrorMessage(() => tab.grow(target - initial), RangeError, /failed to grow table/);
    246 }
    247 
    248 testTableFailGrow(1, undefined, TableMaxRuntime + 1);
    249 testTableFailGrow(1, TableMaxValid, TableMaxRuntime + 1);
    250 
    251 // Testing the maximum number of memories in a single module.
    252 function generateMemories(count) {
    253  let lines = ['(module'];
    254  for (let i = 0; i < count; i++) {
    255    lines.push(`  (memory 10 50)`);
    256  }
    257  lines.push(')');
    258  return lines.join('\n');
    259 }
    260 
    261 wasmValidateText(generateMemories(MaxMemories));
    262 
    263 assertErrorMessage(() => wasmEvalText(generateMemories(MaxMemories+1)),
    264    WebAssembly.CompileError, /too many memories/);