tor-browser

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

passive-segs-partial-table.js (6291B)


      1 // Sundry test cases for the "partial write" bounds checking semantics.
      2 
      3 // table.init: out of bounds of the table or the element segment, and should
      4 // not perform the operation at all.
      5 //
      6 // Arithmetic overflow of tableoffset + len or of segmentoffset + len should not
      7 // affect the behavior.
      8 
      9 // Note, the length of the element segment is 16.
     10 const tbl_init_len = 16;
     11 
     12 function tbl_init(min, max, backup, write, segoffs=0) {
     13    let ins = wasmEvalText(
     14        `(module
     15           (table (export "tbl") ${min} ${max} funcref)
     16           (elem func $f0 $f1 $f2 $f3 $f4 $f5 $f6 $f7 $f8 $f9 $f10 $f11 $f12 $f13 $f14 $f15)
     17           (func $f0 (export "f0"))
     18           (func $f1 (export "f1"))
     19           (func $f2 (export "f2"))
     20           (func $f3 (export "f3"))
     21           (func $f4 (export "f4"))
     22           (func $f5 (export "f5"))
     23           (func $f6 (export "f6"))
     24           (func $f7 (export "f7"))
     25           (func $f8 (export "f8"))
     26           (func $f9 (export "f9"))
     27           (func $f10 (export "f10"))
     28           (func $f11 (export "f11"))
     29           (func $f12 (export "f12"))
     30           (func $f13 (export "f13"))
     31           (func $f14 (export "f14"))
     32           (func $f15 (export "f15"))
     33           (func (export "run") (param $offs i32) (param $len i32)
     34             (table.init 0 (local.get $offs) (i32.const ${segoffs}) (local.get $len))))`);
     35    // A fill writing past the end of the table should throw *and* have filled
     36    // all the way up to the end.
     37    //
     38    // A fill reading past the end of the segment should throw *and* have filled
     39    // table with as much data as was available.
     40    let offs = min - backup;
     41    assertErrorMessage(() => ins.exports.run(offs, write),
     42                       WebAssembly.RuntimeError,
     43                       /index out of bounds/);
     44    let tbl = ins.exports.tbl;
     45    for (let i=0; i < min; i++) {
     46        assertEq(tbl.get(i), null);
     47    }
     48 }
     49 
     50 // We exceed the bounds of the table but not of the element segment
     51 tbl_init(tbl_init_len*2, tbl_init_len*4, Math.floor(tbl_init_len/2), tbl_init_len);
     52 tbl_init(tbl_init_len*2, tbl_init_len*4, Math.floor(tbl_init_len/2)-1, tbl_init_len);
     53 
     54 // We exceed the bounds of the element segment but not the table
     55 tbl_init(tbl_init_len*10, tbl_init_len*20, tbl_init_len*4, tbl_init_len*2);
     56 tbl_init(tbl_init_len*10, tbl_init_len*20, tbl_init_len*4-1, tbl_init_len*2-1);
     57 
     58 // We arithmetically overflow the table limit but not the segment limit
     59 tbl_init(tbl_init_len*4, tbl_init_len*4, tbl_init_len, 0xFFFFFFF0);
     60 
     61 // We arithmetically overflow the segment limit but not the table limit
     62 tbl_init(tbl_init_len, tbl_init_len, tbl_init_len, 0xFFFFFFFC, Math.floor(tbl_init_len/2));
     63 
     64 // table.copy: out of bounds of the table for the source or target, and should
     65 // perform the operation at all.  Major cases:
     66 //
     67 // - non-overlapping regions
     68 // - overlapping regions with src > dest
     69 // - overlapping regions with src == dest
     70 // - overlapping regions with src < dest
     71 // - arithmetic overflow on src addresses
     72 // - arithmetic overflow on target addresses
     73 //
     74 // for each of those,
     75 //
     76 // - src address oob
     77 // - target address oob
     78 // - both oob
     79 //
     80 // Note we do not test the multi-table case here because that is part of the
     81 // reftypes proposal; tests are in the gc/ subdirectory.
     82 
     83 const tbl_copy_len = 16;
     84 
     85 function tbl_copy(min, max, srcOffs, targetOffs, len) {
     86    let ins = wasmEvalText(
     87        `(module
     88           (table (export "tbl") ${min} ${max} funcref)
     89           (func $f0 (export "f0"))
     90           (func $f1 (export "f1"))
     91           (func $f2 (export "f2"))
     92           (func $f3 (export "f3"))
     93           (func $f4 (export "f4"))
     94           (func $f5 (export "f5"))
     95           (func $f6 (export "f6"))
     96           (func $f7 (export "f7"))
     97           (func $f8 (export "f8"))
     98           (func $f9 (export "f9"))
     99           (func $f10 (export "f10"))
    100           (func $f11 (export "f11"))
    101           (func $f12 (export "f12"))
    102           (func $f13 (export "f13"))
    103           (func $f14 (export "f14"))
    104           (func $f15 (export "f15"))
    105           (func (export "run") (param $targetOffs i32) (param $srcOffs i32) (param $len i32)
    106             (table.copy (local.get $targetOffs) (local.get $srcOffs) (local.get $len))))`);
    107 
    108    let tbl = ins.exports.tbl;
    109 
    110    let copyDown = srcOffs < targetOffs;
    111    let targetAvail = tbl.length - targetOffs;
    112    let srcAvail = tbl.length - srcOffs;
    113    let srcLim = srcOffs + Math.min(len, targetAvail, srcAvail);
    114 
    115    for (let i=srcOffs, j=0; i < srcLim; i++, j++)
    116        tbl.set(i, ins.exports["f" + j]);
    117    assertErrorMessage(() => ins.exports.run(targetOffs, srcOffs, len),
    118                       WebAssembly.RuntimeError,
    119                       /index out of bounds/);
    120 
    121    for (var i=0, s=0; i < tbl.length; i++ ) {
    122        if (i >= srcOffs && i < srcLim) {
    123            assertEq(tbl.get(i), ins.exports["f" + (s++)]);
    124            continue;
    125        }
    126        assertEq(tbl.get(i), null);
    127    }
    128 }
    129 
    130 // OOB target address, nonoverlapping
    131 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, 0, Math.floor(1.5*tbl_copy_len), tbl_copy_len);
    132 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, 0, Math.floor(1.5*tbl_copy_len)-1, tbl_copy_len-1);
    133 
    134 // OOB source address, nonoverlapping
    135 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), 0, tbl_copy_len);
    136 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len)-1, 0, tbl_copy_len-1);
    137 
    138 // OOB target address, overlapping, src < target
    139 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len-5, Math.floor(1.5*tbl_copy_len), tbl_copy_len);
    140 
    141 // OOB source address, overlapping, target < src
    142 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), tbl_copy_len-5, tbl_copy_len);
    143 
    144 // OOB both, overlapping, including src == target
    145 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len+5, Math.floor(1.5*tbl_copy_len), tbl_copy_len);
    146 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, Math.floor(1.5*tbl_copy_len), tbl_copy_len+5, tbl_copy_len);
    147 tbl_copy(tbl_copy_len*2, tbl_copy_len*4, tbl_copy_len+5, tbl_copy_len+5, tbl_copy_len);
    148 
    149 // Arithmetic overflow on source address.
    150 tbl_copy(tbl_copy_len*8, tbl_copy_len*8, tbl_copy_len*7, 0, 0xFFFFFFE0);
    151 
    152 // Arithmetic overflow on target adddress is an overlapping case.
    153 tbl_copy(tbl_copy_len*8, tbl_copy_len*8, 0, tbl_copy_len*7, 0xFFFFFFE0);