tor-browser

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

passive-segs-partial-mem.js (6478B)


      1 if (getBuildConfiguration("debug") &&
      2    (getBuildConfiguration("arm-simulator") || getBuildConfiguration("arm64-simulator") ||
      3     getBuildConfiguration("mips64-simulator")))
      4 {
      5    // Will timeout, so just quit early.
      6    quit(0);
      7 }
      8 
      9 // Sundry test cases for the "partial write" bounds checking semantics.
     10 
     11 const PAGESIZE = 65536;
     12 
     13 // memory.fill: out of bounds, should not perform writes
     14 //
     15 // Arithmetic overflow of memory offset + len should not affect the behavior, we
     16 // should still fill up to the limit.
     17 
     18 function mem_fill(min, max, shared, backup, write=backup*2) {
     19    if (shared == "shared" && !sharedMemoryEnabled())
     20        return;
     21    let ins = wasmEvalText(
     22        `(module
     23           (memory (export "mem") ${min} ${max} ${shared})
     24           (func (export "run") (param $offs i32) (param $val i32) (param $len i32)
     25             (memory.fill (local.get $offs) (local.get $val) (local.get $len))))`);
     26    // A fill past the end should throw *and* not have filled all the way up to
     27    // the end
     28    let offs = min*PAGESIZE - backup;
     29    let val = 37;
     30    assertErrorMessage(() => ins.exports.run(offs, val, write),
     31                       WebAssembly.RuntimeError,
     32                       /index out of bounds/);
     33    let v = new Uint8Array(ins.exports.mem.buffer);
     34    for (let i=0; i < backup; i++)
     35        assertEq(v[offs+i], 0);
     36    for (let i=0; i < offs; i++)
     37        assertEq(v[i], 0);
     38 }
     39 
     40 mem_fill(1, 1, "", 256);
     41 mem_fill(1, 1, "", 257);
     42 mem_fill(1, 1, "", 257, 0xFFFFFFFF); // offs + len overflows 32-bit
     43 
     44 mem_fill(2, 4, "shared", 256);
     45 mem_fill(2, 4, "shared", 257);
     46 mem_fill(2, 4, "shared", 257, 0xFFFFFFFF); // offs + len overflows 32-bit
     47 
     48 // memory.init: out of bounds of the memory or the segment, and should not perform
     49 // the operation at all.
     50 //
     51 // Arithmetic overflow of memoffset + len or of bufferoffset + len should not
     52 // affect the behavior.
     53 
     54 // Note, the length of the data segment is 16.
     55 const mem_init_len = 16;
     56 
     57 function mem_init(min, max, shared, backup, write) {
     58    if (shared == "shared" && !sharedMemoryEnabled())
     59        return;
     60    let ins = wasmEvalText(
     61        `(module
     62           (memory (export "mem") ${min} ${max} ${shared})
     63           (data "\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42\\42")
     64           (func (export "run") (param $offs i32) (param $len i32)
     65             (memory.init 0 (local.get $offs) (i32.const 0) (local.get $len))))`);
     66    // A fill writing past the end of the memory should throw *and* not have filled
     67    // all the way up to the end.
     68    //
     69    // A fill reading past the end of the segment should throw *and* not have filled
     70    // memory with as much data as was available.
     71    let offs = min*PAGESIZE - backup;
     72    assertErrorMessage(() => ins.exports.run(offs, write),
     73                       WebAssembly.RuntimeError,
     74                       /index out of bounds/);
     75    let v = new Uint8Array(ins.exports.mem.buffer);
     76    for (let i=0; i < min; i++)
     77        assertEq(v[offs + i], 0);
     78 }
     79 
     80 // We exceed the bounds of the memory but not of the data segment
     81 mem_init(1, 1, "", Math.floor(mem_init_len/2), mem_init_len);
     82 mem_init(1, 1, "", Math.floor(mem_init_len/2)+1, mem_init_len);
     83 mem_init(2, 4, "shared", Math.floor(mem_init_len/2), mem_init_len);
     84 mem_init(2, 4, "shared", Math.floor(mem_init_len/2)+1, mem_init_len);
     85 
     86 // We exceed the bounds of the data segment but not the memory
     87 mem_init(1, 1, "", mem_init_len*4, mem_init_len*2-2);
     88 mem_init(1, 1, "", mem_init_len*4-1, mem_init_len*2-1);
     89 mem_init(2, 4, "shared", mem_init_len*4, mem_init_len*2-2);
     90 mem_init(2, 4, "shared", mem_init_len*4-1, mem_init_len*2-1);
     91 
     92 // We arithmetically overflow the memory limit but not the segment limit
     93 mem_init(1, "", "", Math.floor(mem_init_len/2), 0xFFFFFF00);
     94 
     95 // We arithmetically overflow the segment limit but not the memory limit
     96 mem_init(1, "", "", PAGESIZE, 0xFFFFFFFC);
     97 
     98 // memory.copy: out of bounds of the memory for the source or target, and should
     99 // not perform at all.  Major cases:
    100 //
    101 // - non-overlapping regions
    102 // - overlapping regions with src >= dest
    103 // - overlapping regions with src == dest
    104 // - overlapping regions with src < dest
    105 // - arithmetic overflow on src addresses
    106 // - arithmetic overflow on target addresses
    107 //
    108 // for each of those,
    109 //
    110 // - src address oob
    111 // - target address oob
    112 // - both oob
    113 
    114 function mem_copy(min, max, shared, srcOffs, targetOffs, len) {
    115    if (shared == "shared" && !sharedMemoryEnabled())
    116        return;
    117    let ins = wasmEvalText(
    118        `(module
    119           (memory (export "mem") ${min} ${max} ${shared})
    120           (func (export "run") (param $targetOffs i32) (param $srcOffs i32) (param $len i32)
    121             (memory.copy (local.get $targetOffs) (local.get $srcOffs) (local.get $len))))`);
    122 
    123    let v = new Uint8Array(ins.exports.mem.buffer);
    124 
    125    let copyDown = srcOffs < targetOffs;
    126    let targetAvail = v.length - targetOffs;
    127    let srcAvail = v.length - srcOffs;
    128    let srcLim = srcOffs + Math.min(len, targetAvail, srcAvail);
    129 
    130    for (let i=srcOffs, j=0; i < srcLim; i++, j++)
    131        v[i] = j;
    132    assertErrorMessage(() => ins.exports.run(targetOffs, srcOffs, len),
    133                       WebAssembly.RuntimeError,
    134                       /index out of bounds/);
    135 
    136    for (var i=0, s=0; i < v.length; i++ ) {
    137        if (i >= srcOffs && i < srcLim) {
    138            assertEq(v[i], (s++) & 0xFF);
    139            continue;
    140        }
    141        assertEq(v[i], 0);
    142    }
    143 }
    144 
    145 // OOB target address, nonoverlapping
    146 mem_copy(1, 1, "", 0, PAGESIZE-20, 40);
    147 mem_copy(1, 1, "", 0, PAGESIZE-21, 39);
    148 mem_copy(2, 4, "shared", 0, 2*PAGESIZE-20, 40);
    149 mem_copy(2, 4, "shared", 0, 2*PAGESIZE-21, 39);
    150 
    151 // OOB source address, nonoverlapping
    152 mem_copy(1, 1, "", PAGESIZE-20, 0, 40);
    153 mem_copy(1, 1, "", PAGESIZE-21, 0, 39);
    154 mem_copy(2, 4, "shared", 2*PAGESIZE-20, 0, 40);
    155 mem_copy(2, 4, "shared", 2*PAGESIZE-21, 0, 39);
    156 
    157 // OOB target address, overlapping, src < target
    158 mem_copy(1, 1, "", PAGESIZE-50, PAGESIZE-20, 40);
    159 
    160 // OOB source address, overlapping, target < src
    161 mem_copy(1, 1, "", PAGESIZE-20, PAGESIZE-50, 40);
    162 
    163 // OOB both, overlapping, including target == src
    164 mem_copy(1, 1, "", PAGESIZE-30, PAGESIZE-20, 40);
    165 mem_copy(1, 1, "", PAGESIZE-20, PAGESIZE-30, 40);
    166 mem_copy(1, 1, "", PAGESIZE-20, PAGESIZE-20, 40);
    167 
    168 // Arithmetic overflow on source address.
    169 mem_copy(1, "", "", PAGESIZE-20, 0, 0xFFFFF000);
    170 
    171 // Arithmetic overflow on target adddress is an overlapping case.
    172 mem_copy(1, 1, "", PAGESIZE-0x1000, PAGESIZE-20, 0xFFFFFF00);