ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
33.56k stars 2.45k forks source link

[WebAssembly] `memcpy` does not result in no-op for zero-length slices #16360

Open Luukdegram opened 1 year ago

Luukdegram commented 1 year ago

Zig Version

0.11.0-dev.3947+89396ff02

Steps to Reproduce and Observed Behavior

Given the following program and CLI input:

./stage2/bin/zig build-lib foo.zig -femit-bin=test.wasm -dynamic -mcpu=mvp+bulk_memory -target wasm32-freestanding --export=_start
const std = @import("std");
export fn _start() void {
    var ptr = foo();
    var dest = foo();
    @memcpy(dest, ptr);
}

fn foo() []u8 {
    const ptr = comptime std.mem.alignBackward(usize, std.math.maxInt(usize), 1);
    return @as([*]align(1) u8, @ptrFromInt(ptr))[0..0];
}

results in a program that traps:

> wasmtime test.wasm                                                                                                                                                                                                                                                                                                  07/08/2023 04:20:37 PM
Error: failed to run main module `test.wasm`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
           0:   0xd4 - _start
                           at /Users/luuk/dev/zig-dev/foo.zig:6:5
    2: wasm trap: out of bounds memory access

This is due to Wasm's memory.copy instruction trapping when the source -or destination address is out-of-bounds regardless of the length operand.

Expected Behavior

I expected zero-length memset/memcpy to result in a no-op and not trap.

Luukdegram commented 1 year ago

This is a tracking issue for upstream: https://github.com/llvm/llvm-project/issues/63755, and can only be closed once the upstream bug has been fixed and landed downstream in Zig.