...
1;; segment syntax
2(module
3 (memory 1)
4 (data "foo"))
5
6(module
7 (table 3 funcref)
8 (elem funcref (ref.func 0) (ref.null func) (ref.func 1))
9 (func)
10 (func))
11
12;; memory.fill
13(module
14 (memory 1)
15
16 (func (export "fill") (param i32 i32 i32)
17 (memory.fill
18 (local.get 0)
19 (local.get 1)
20 (local.get 2)))
21
22 (func (export "load8_u") (param i32) (result i32)
23 (i32.load8_u (local.get 0)))
24)
25
26;; Basic fill test.
27(invoke "fill" (i32.const 1) (i32.const 0xff) (i32.const 3))
28(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0))
29(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xff))
30(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0xff))
31(assert_return (invoke "load8_u" (i32.const 3)) (i32.const 0xff))
32(assert_return (invoke "load8_u" (i32.const 4)) (i32.const 0))
33
34;; Fill value is stored as a byte.
35(invoke "fill" (i32.const 0) (i32.const 0xbbaa) (i32.const 2))
36(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xaa))
37(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xaa))
38
39;; Fill all of memory
40(invoke "fill" (i32.const 0) (i32.const 0) (i32.const 0x10000))
41
42;; Out-of-bounds writes trap, and nothing is written
43(assert_trap (invoke "fill" (i32.const 0xff00) (i32.const 1) (i32.const 0x101))
44 "out of bounds memory access")
45(assert_return (invoke "load8_u" (i32.const 0xff00)) (i32.const 0))
46(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0))
47
48;; Succeed when writing 0 bytes at the end of the region.
49(invoke "fill" (i32.const 0x10000) (i32.const 0) (i32.const 0))
50
51;; Writing 0 bytes outside the memory traps.
52(assert_trap (invoke "fill" (i32.const 0x10001) (i32.const 0) (i32.const 0))
53 "out of bounds memory access")
54
55
56;; memory.copy
57(module
58 (memory (data "\aa\bb\cc\dd"))
59
60 (func (export "copy") (param i32 i32 i32)
61 (memory.copy
62 (local.get 0)
63 (local.get 1)
64 (local.get 2)))
65
66 (func (export "load8_u") (param i32) (result i32)
67 (i32.load8_u (local.get 0)))
68)
69
70;; Non-overlapping copy.
71(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4))
72
73(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0))
74(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa))
75(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb))
76(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc))
77(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd))
78(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0))
79
80;; Overlap, source > dest
81(invoke "copy" (i32.const 8) (i32.const 10) (i32.const 4))
82(assert_return (invoke "load8_u" (i32.const 8)) (i32.const 0xaa))
83(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0xbb))
84(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xcc))
85(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xdd))
86(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc))
87(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd))
88
89;; Overlap, source < dest
90(invoke "copy" (i32.const 10) (i32.const 7) (i32.const 6))
91(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0))
92(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa))
93(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb))
94(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc))
95(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd))
96(assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc))
97(assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0))
98
99;; Copy ending at memory limit is ok.
100(invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100))
101(invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100))
102
103;; Succeed when copying 0 bytes at the end of the region.
104(invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0))
105(invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0))
106
107;; Copying 0 bytes outside the memory traps.
108(assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0))
109 "out of bounds memory access")
110(assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0))
111 "out of bounds memory access")
112
113
114;; memory.init
115(module
116 (memory 1)
117 (data "\aa\bb\cc\dd")
118
119 (func (export "init") (param i32 i32 i32)
120 (memory.init 0
121 (local.get 0)
122 (local.get 1)
123 (local.get 2)))
124
125 (func (export "load8_u") (param i32) (result i32)
126 (i32.load8_u (local.get 0)))
127)
128
129(invoke "init" (i32.const 0) (i32.const 1) (i32.const 2))
130(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xbb))
131(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xcc))
132(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0))
133
134;; Init ending at memory limit and segment limit is ok.
135(invoke "init" (i32.const 0xfffc) (i32.const 0) (i32.const 4))
136
137;; Out-of-bounds writes trap, and nothing is written.
138(assert_trap (invoke "init" (i32.const 0xfffe) (i32.const 0) (i32.const 3))
139 "out of bounds memory access")
140(assert_return (invoke "load8_u" (i32.const 0xfffe)) (i32.const 0xcc))
141(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0xdd))
142
143;; Succeed when writing 0 bytes at the end of either region.
144(invoke "init" (i32.const 0x10000) (i32.const 0) (i32.const 0))
145(invoke "init" (i32.const 0) (i32.const 4) (i32.const 0))
146
147;; Writing 0 bytes outside the memory traps.
148(assert_trap (invoke "init" (i32.const 0x10001) (i32.const 0) (i32.const 0))
149 "out of bounds memory access")
150(assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0))
151 "out of bounds memory access")
152
153;; data.drop
154(module
155 (memory 1)
156 (data $p "x")
157 (data $a (memory 0) (i32.const 0) "x")
158
159 (func (export "drop_passive") (data.drop $p))
160 (func (export "init_passive") (param $len i32)
161 (memory.init $p (i32.const 0) (i32.const 0) (local.get $len)))
162
163 (func (export "drop_active") (data.drop $a))
164 (func (export "init_active") (param $len i32)
165 (memory.init $a (i32.const 0) (i32.const 0) (local.get $len)))
166)
167
168(invoke "init_passive" (i32.const 1))
169(invoke "drop_passive")
170(invoke "drop_passive")
171(assert_return (invoke "init_passive" (i32.const 0)))
172(assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds memory access")
173(invoke "init_passive" (i32.const 0))
174(invoke "drop_active")
175(assert_return (invoke "init_active" (i32.const 0)))
176(assert_trap (invoke "init_active" (i32.const 1)) "out of bounds memory access")
177(invoke "init_active" (i32.const 0))
178
179;; Test that the data segment index is properly encoded as an unsigned (not
180;; signed) LEB.
181(module
182 ;; 65 data segments. 64 is the smallest positive number that is encoded
183 ;; differently as a signed LEB.
184 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
185 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
186 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
187 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
188 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
189 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
190 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
191 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "")
192 (data "")
193 (func (data.drop 64)))
194
195;; No memory is required for the data.drop instruction.
196(module (data "goodbye") (func (data.drop 0)))
197
198;; table.init
199(module
200 (table 3 funcref)
201 (elem funcref
202 (ref.func $zero) (ref.func $one) (ref.func $zero) (ref.func $one))
203
204 (func $zero (result i32) (i32.const 0))
205 (func $one (result i32) (i32.const 1))
206
207 (func (export "init") (param i32 i32 i32)
208 (table.init 0
209 (local.get 0)
210 (local.get 1)
211 (local.get 2)))
212
213 (func (export "call") (param i32) (result i32)
214 (call_indirect (result i32)
215 (local.get 0)))
216)
217
218;; Out-of-bounds stores trap, and nothing is written.
219(assert_trap (invoke "init" (i32.const 2) (i32.const 0) (i32.const 2))
220 "out of bounds table access")
221(assert_trap (invoke "call" (i32.const 2))
222 "uninitialized element 2")
223
224(invoke "init" (i32.const 0) (i32.const 1) (i32.const 2))
225(assert_return (invoke "call" (i32.const 0)) (i32.const 1))
226(assert_return (invoke "call" (i32.const 1)) (i32.const 0))
227(assert_trap (invoke "call" (i32.const 2)) "uninitialized element")
228
229;; Init ending at table limit and segment limit is ok.
230(invoke "init" (i32.const 1) (i32.const 2) (i32.const 2))
231
232;; Succeed when storing 0 elements at the end of either region.
233(invoke "init" (i32.const 3) (i32.const 0) (i32.const 0))
234(invoke "init" (i32.const 0) (i32.const 4) (i32.const 0))
235
236;; Writing 0 elements outside the table traps.
237(assert_trap (invoke "init" (i32.const 4) (i32.const 0) (i32.const 0))
238 "out of bounds table access")
239(assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0))
240 "out of bounds table access")
241
242
243;; elem.drop
244(module
245 (table 1 funcref)
246 (func $f)
247 (elem $p funcref (ref.func $f))
248 (elem $a (table 0) (i32.const 0) func $f)
249
250 (func (export "drop_passive") (elem.drop $p))
251 (func (export "init_passive") (param $len i32)
252 (table.init $p (i32.const 0) (i32.const 0) (local.get $len))
253 )
254
255 (func (export "drop_active") (elem.drop $a))
256 (func (export "init_active") (param $len i32)
257 (table.init $a (i32.const 0) (i32.const 0) (local.get $len))
258 )
259)
260
261(invoke "init_passive" (i32.const 1))
262(invoke "drop_passive")
263(invoke "drop_passive")
264(assert_return (invoke "init_passive" (i32.const 0)))
265(assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds table access")
266(invoke "init_passive" (i32.const 0))
267(invoke "drop_active")
268(assert_return (invoke "init_active" (i32.const 0)))
269(assert_trap (invoke "init_active" (i32.const 1)) "out of bounds table access")
270(invoke "init_active" (i32.const 0))
271
272;; Test that the elem segment index is properly encoded as an unsigned (not
273;; signed) LEB.
274(module
275 ;; 65 elem segments. 64 is the smallest positive number that is encoded
276 ;; differently as a signed LEB.
277 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
278 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
279 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
280 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
281 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
282 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
283 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
284 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
285 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
286 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
287 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
288 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
289 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
290 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
291 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
292 (elem funcref) (elem funcref) (elem funcref) (elem funcref)
293 (elem funcref)
294 (func (elem.drop 64)))
295
296;; No table is required for the elem.drop instruction.
297(module (elem funcref (ref.func 0)) (func (elem.drop 0)))
298
299;; table.copy
300(module
301 (table 10 funcref)
302 (elem (i32.const 0) $zero $one $two)
303 (func $zero (result i32) (i32.const 0))
304 (func $one (result i32) (i32.const 1))
305 (func $two (result i32) (i32.const 2))
306
307 (func (export "copy") (param i32 i32 i32)
308 (table.copy
309 (local.get 0)
310 (local.get 1)
311 (local.get 2)))
312
313 (func (export "call") (param i32) (result i32)
314 (call_indirect (result i32)
315 (local.get 0)))
316)
317
318;; Non-overlapping copy.
319(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 3))
320;; Now [$zero, $one, $two, $zero, $one, $two, ...]
321(assert_return (invoke "call" (i32.const 3)) (i32.const 0))
322(assert_return (invoke "call" (i32.const 4)) (i32.const 1))
323(assert_return (invoke "call" (i32.const 5)) (i32.const 2))
324
325;; Overlap, source > dest
326(invoke "copy" (i32.const 0) (i32.const 1) (i32.const 3))
327;; Now [$one, $two, $zero, $zero, $one, $two, ...]
328(assert_return (invoke "call" (i32.const 0)) (i32.const 1))
329(assert_return (invoke "call" (i32.const 1)) (i32.const 2))
330(assert_return (invoke "call" (i32.const 2)) (i32.const 0))
331
332;; Overlap, source < dest
333(invoke "copy" (i32.const 2) (i32.const 0) (i32.const 3))
334;; Now [$one, $two, $one, $two, $zero, $two, ...]
335(assert_return (invoke "call" (i32.const 2)) (i32.const 1))
336(assert_return (invoke "call" (i32.const 3)) (i32.const 2))
337(assert_return (invoke "call" (i32.const 4)) (i32.const 0))
338
339;; Copy ending at table limit is ok.
340(invoke "copy" (i32.const 6) (i32.const 8) (i32.const 2))
341(invoke "copy" (i32.const 8) (i32.const 6) (i32.const 2))
342
343;; Succeed when copying 0 elements at the end of the region.
344(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 0))
345(invoke "copy" (i32.const 0) (i32.const 10) (i32.const 0))
346
347;; Fail on out-of-bounds when copying 0 elements outside of table.
348(assert_trap (invoke "copy" (i32.const 11) (i32.const 0) (i32.const 0))
349 "out of bounds table access")
350(assert_trap (invoke "copy" (i32.const 0) (i32.const 11) (i32.const 0))
351 "out of bounds table access")
View as plain text