big-arrays.js (7040B)
1 // |jit-test| slow; allow-oom; skip-if: getBuildConfiguration("simulator") 2 3 ////////////////////////////////////////////////////////////////////////////// 4 // 5 // Checks for requests for oversize arrays (more than MaxArrayPayloadBytes), 6 // where MaxArrayPayloadBytes == 1,987,654,321. 7 8 const MaxArrayPayloadBytes = 1987654321; 9 10 function maxNumElementsForSize(bytes, elemSize) { 11 let n = bytes; 12 n = bytes & ~0b111; // round down to nearest multiple of gc::CellAlignSize 13 n -= getBuildConfiguration()['pointer-byte-size']; // subtract size of data header 14 n = Math.floor(n / elemSize); // divide by elemSize and round down 15 return n; 16 } 17 18 // // Test code for maxNumElementsForSize 19 // for (const bytes of [32, 33, 112]) { 20 // for (const size of [1, 2, 4, 8, 16]) { 21 // print(bytes, size, "->", maxNumElementsForSize(bytes, size)); 22 // } 23 // } 24 // throw "see above"; 25 26 // array.new 27 { 28 const { test1, test2, test4, test8, test16 } = wasmEvalText(`(module 29 (type $1 (array i8)) 30 (type $2 (array i16)) 31 (type $4 (array i32)) 32 (type $8 (array i64)) 33 ${wasmSimdEnabled() ? ` 34 (type $16 (array v128)) 35 ` : ""} 36 (func (export "test1") (param i32) (result eqref) 37 (array.new $1 (i32.const 0xAB) (local.get 0)) 38 ) 39 (func (export "test2") (param i32) (result eqref) 40 (array.new $2 (i32.const 0xCD) (local.get 0)) 41 ) 42 (func (export "test4") (param i32) (result eqref) 43 (array.new $4 (i32.const 0xABCD1234) (local.get 0)) 44 ) 45 (func (export "test8") (param i32) (result eqref) 46 (array.new $8 (i64.const 0xABCD1234) (local.get 0)) 47 ) 48 ${wasmSimdEnabled() ? ` 49 (func (export "test16") (param i32) (result eqref) 50 (array.new $16 (v128.const i64x2 0xABCD1234 0xABCD1234) (local.get 0)) 51 ) 52 ` : ""} 53 )`).exports; 54 55 const tests = [[1, test1], [2, test2], [4, test4], [8, test8]]; 56 if (wasmSimdEnabled()) { 57 tests.push([16, test16]); 58 } 59 for (const [size, test] of tests) { 60 for (const doMasm of [false, true]) { 61 if (doMasm) { 62 // Prime the alloc site with a successful allocation so we hit masm from here on out 63 test(0); 64 } 65 66 // Test boundaries of implementation limit 67 const maxNumElements = maxNumElementsForSize(MaxArrayPayloadBytes, size); 68 test(maxNumElements); 69 assertErrorMessage(() => test(maxNumElements + 1), WebAssembly.RuntimeError, /too many array elements/); 70 71 // Test around signed overflow boundary 72 for (let i = -16; i <= 16; i++) { 73 assertErrorMessage( 74 () => test(maxNumElementsForSize(Math.pow(2, 31) + i, size)), 75 WebAssembly.RuntimeError, 76 /too many array elements/, 77 ); 78 } 79 80 // Test around unsigned overflow boundary 81 for (let i = -16; i <= -1; i++) { 82 assertErrorMessage(() => test(i), WebAssembly.RuntimeError, /too many array elements/); 83 } 84 } 85 } 86 } 87 88 // array.new_default 89 { 90 const { test1, test2, test4, test8, test16 } = wasmEvalText(`(module 91 (type $1 (array i8)) 92 (type $2 (array i16)) 93 (type $4 (array i32)) 94 (type $8 (array i64)) 95 ${wasmSimdEnabled() ? ` 96 (type $16 (array v128)) 97 ` : ""} 98 (func (export "test1") (param i32) (result eqref) 99 (array.new_default $1 (local.get 0)) 100 ) 101 (func (export "test2") (param i32) (result eqref) 102 (array.new_default $2 (local.get 0)) 103 ) 104 (func (export "test4") (param i32) (result eqref) 105 (array.new_default $4 (local.get 0)) 106 ) 107 (func (export "test8") (param i32) (result eqref) 108 (array.new_default $8 (local.get 0)) 109 ) 110 ${wasmSimdEnabled() ? ` 111 (func (export "test16") (param i32) (result eqref) 112 (array.new_default $16 (local.get 0)) 113 ) 114 ` : ""} 115 )`).exports; 116 117 const tests = [[1, test1], [2, test2], [4, test4], [8, test8]]; 118 if (wasmSimdEnabled()) { 119 tests.push([16, test16]); 120 } 121 for (const [size, test] of tests) { 122 for (const doMasm of [false, true]) { 123 if (doMasm) { 124 // Prime the alloc site with a successful allocation so we hit masm from here on out 125 test(0); 126 } 127 128 // Test boundaries of implementation limit 129 const maxNumElements = maxNumElementsForSize(MaxArrayPayloadBytes, size); 130 test(maxNumElements); 131 assertErrorMessage(() => test(maxNumElements + 1), WebAssembly.RuntimeError, /too many array elements/); 132 133 // Test around signed overflow boundary 134 for (let i = -16; i <= 16; i++) { 135 assertErrorMessage( 136 () => test(maxNumElementsForSize(Math.pow(2, 31) + i, size)), 137 WebAssembly.RuntimeError, 138 /too many array elements/, 139 ); 140 } 141 142 // Test around unsigned overflow boundary 143 for (let i = -16; i <= -1; i++) { 144 assertErrorMessage(() => test(i), WebAssembly.RuntimeError, /too many array elements/); 145 } 146 } 147 } 148 } 149 150 // array.new_fixed 151 { 152 assertErrorMessage(() => wasmEvalText(`(module 153 (type $a (array i8)) 154 (func (result (ref $a)) 155 array.new_fixed $a 10001 156 ) 157 )`), WebAssembly.CompileError, /too many array.new_fixed elements/); 158 assertErrorMessage(() => wasmEvalText(`(module 159 (type $a (array f32)) 160 (func (result (ref $a)) 161 array.new_fixed $a 10001 162 ) 163 )`), WebAssembly.CompileError, /too many array.new_fixed elements/); 164 assertErrorMessage(() => wasmEvalText(`(module 165 (type $a (array f32)) 166 (func (result (ref $a)) 167 array.new_fixed $a 2147483647 168 ) 169 )`), WebAssembly.CompileError, /too many array.new_fixed elements/); 170 assertErrorMessage(() => wasmEvalText(`(module 171 (type $a (array i8)) 172 (func (result (ref $a)) 173 array.new_fixed $a 4294967295 174 ) 175 )`), WebAssembly.CompileError, /too many array.new_fixed elements/); 176 } 177 178 // array.new (constant length) 179 { 180 const { testA, testB, testC, testD } = wasmEvalText(`(module 181 (type $a (array f32)) 182 (type $b (array i8)) 183 184 (func (export "testA") (result (ref $a)) 185 (array.new $a (f32.const 0) (i32.const 2147483647)) 186 ) 187 (func (export "testB") (result (ref $b)) 188 ;; overflows due to size of data header 189 (array.new $b (i32.const 0) (i32.const 4294967295)) 190 ) 191 (func (export "testC") (result (ref $a)) 192 (array.new $a (f32.const 0) (i32.const -1)) 193 ) 194 (func (export "testD") (result (ref $b)) 195 (array.new $b (i32.const 0) (i32.const -1)) 196 ) 197 )`).exports; 198 assertErrorMessage(() => testA(), WebAssembly.RuntimeError, /too many array elements/); 199 assertErrorMessage(() => testB(), WebAssembly.RuntimeError, /too many array elements/); 200 assertErrorMessage(() => testC(), WebAssembly.RuntimeError, /too many array elements/); 201 assertErrorMessage(() => testD(), WebAssembly.RuntimeError, /too many array elements/); 202 } 203 204 // array.new_data 205 // Impossible to test because the max data segment length is 1GB 206 // (1,073,741,824 bytes) (MaxDataSegmentLengthPages * PageSize), which is less 207 // than MaxArrayPayloadBytes. 208 209 // array.new_element 210 // Similarly, impossible to test because an element segment can contain at 211 // most 10,000,000 (MaxElemSegmentLength) entries.