| ;; Passive segment syntax |
| (module |
| (memory 1) |
| (data "foo")) |
| |
| ;; memory.fill |
| (module |
| (memory 1) |
| |
| (func (export "fill") (param i32 i32 i32) |
| (memory.fill |
| (local.get 0) |
| (local.get 1) |
| (local.get 2))) |
| |
| (func (export "load8_u") (param i32) (result i32) |
| (i32.load8_u (local.get 0))) |
| ) |
| |
| ;; Basic fill test. |
| (invoke "fill" (i32.const 1) (i32.const 0xff) (i32.const 3)) |
| (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0)) |
| (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xff)) |
| (assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0xff)) |
| (assert_return (invoke "load8_u" (i32.const 3)) (i32.const 0xff)) |
| (assert_return (invoke "load8_u" (i32.const 4)) (i32.const 0)) |
| |
| ;; Fill value is stored as a byte. |
| (invoke "fill" (i32.const 0) (i32.const 0xbbaa) (i32.const 2)) |
| (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xaa)) |
| (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xaa)) |
| |
| ;; Fill all of memory |
| (invoke "fill" (i32.const 0) (i32.const 0) (i32.const 0x10000)) |
| |
| ;; Succeed when writing 0 bytes at the end of the region. |
| (invoke "fill" (i32.const 0x10000) (i32.const 0) (i32.const 0)) |
| |
| ;; Writing 0 bytes outside of memory limit is NOT allowed. |
| (assert_trap (invoke "fill" (i32.const 0x10001) (i32.const 0) (i32.const 0)) "oob") |
| |
| ;; Negative size |
| (assert_trap (invoke "fill" (i32.const 15) (i32.const 14) (i32.const -2)) "oob") |
| (assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0)) |
| |
| ;; memory.copy |
| (module |
| (memory 1 1) |
| (data (i32.const 0) "\aa\bb\cc\dd") |
| |
| (func (export "copy") (param i32 i32 i32) |
| (memory.copy |
| (local.get 0) |
| (local.get 1) |
| (local.get 2))) |
| |
| (func (export "load8_u") (param i32) (result i32) |
| (i32.load8_u (local.get 0))) |
| ) |
| |
| ;; Non-overlapping copy. |
| (invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) |
| |
| (assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) |
| (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) |
| (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) |
| (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) |
| (assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) |
| |
| ;; Overlap, source > dest |
| (invoke "copy" (i32.const 8) (i32.const 10) (i32.const 4)) |
| (assert_return (invoke "load8_u" (i32.const 8)) (i32.const 0xaa)) |
| (assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0xbb)) |
| (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xdd)) |
| (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) |
| |
| ;; Overlap, source < dest |
| (invoke "copy" (i32.const 10) (i32.const 7) (i32.const 6)) |
| (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0)) |
| (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa)) |
| (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb)) |
| (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd)) |
| (assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0)) |
| |
| ;; Overlap, source < dest but size is out of bounds |
| (assert_trap (invoke "copy" (i32.const 13) (i32.const 11) (i32.const -1)) "oob") |
| (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0)) |
| (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa)) |
| (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb)) |
| (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd)) |
| (assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0)) |
| |
| ;; Copy ending at memory limit is ok. |
| (invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) |
| (invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) |
| |
| ;; Succeed when copying 0 bytes at the end of the region. |
| (invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) |
| (invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) |
| |
| ;; Copying 0 bytes outside of memory limit is NOT allowed. |
| (assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) "oob") |
| (assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) "oob") |
| |
| ;; memory.init |
| (module |
| (memory 1) |
| (data "\aa\bb\cc\dd") |
| |
| (func (export "init") (param i32 i32 i32) |
| (memory.init 0 |
| (local.get 0) |
| (local.get 1) |
| (local.get 2))) |
| |
| (func (export "load8_u") (param i32) (result i32) |
| (i32.load8_u (local.get 0))) |
| ) |
| |
| (invoke "init" (i32.const 0) (i32.const 1) (i32.const 2)) |
| (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xbb)) |
| (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0)) |
| |
| ;; Init ending at memory limit and segment limit is ok. |
| (invoke "init" (i32.const 0xfffc) (i32.const 0) (i32.const 4)) |
| |
| ;; Out-of-bounds writes trap, and no partial writes has been made. |
| (assert_trap (invoke "init" (i32.const 0xfffe) (i32.const 0) (i32.const 3)) |
| "out of bounds memory access") |
| (assert_return (invoke "load8_u" (i32.const 0xfffe)) (i32.const 0xcc)) |
| (assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0xdd)) |
| |
| ;; Succeed when writing 0 bytes at the end of either region. |
| (invoke "init" (i32.const 0x10000) (i32.const 0) (i32.const 0)) |
| (invoke "init" (i32.const 0) (i32.const 4) (i32.const 0)) |
| |
| ;; Writing 0 bytes outside of memory / segment limit is NOT allowed. |
| (assert_trap (invoke "init" (i32.const 0x10001) (i32.const 0) (i32.const 0)) "oob") |
| |
| (assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0)) "oob") |
| |
| ;; OK to access 0 bytes at offset 0 in a dropped segment. |
| (invoke "init" (i32.const 0) (i32.const 0) (i32.const 0)) |
| |
| ;; data.drop |
| (module |
| (memory 1) |
| (data "") |
| (data (i32.const 0) "") |
| |
| (func (export "drop_passive") (data.drop 0)) |
| (func (export "init_passive") |
| (memory.init 0 (i32.const 0) (i32.const 0) (i32.const 0))) |
| |
| (func (export "drop_active") (data.drop 1)) |
| (func (export "init_active") |
| (memory.init 1 (i32.const 0) (i32.const 0) (i32.const 0))) |
| ) |
| |
| ;; OK to drop the same segment multiple times or drop an active segment. |
| (invoke "init_passive") |
| (invoke "drop_passive") |
| (invoke "drop_passive") |
| (invoke "drop_active") |