From ab5a72f6ca9446820f3f516873e1b5d1aeefb5a8 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 14 May 2023 12:48:11 +0300 Subject: [PATCH] Sema: ensure dest ptr of memcpy has length Closes #15513 --- src/Sema.zig | 12 ++++++++++++ test/behavior/memcpy.zig | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 1b55f765f9..f0ebd65a31 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -22130,6 +22130,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const ok = try block.addBinOp(.cmp_eq, dest_len, src_len); try sema.addSafetyCheck(block, ok, .memcpy_len_mismatch); } + } else if (dest_len != .none) { + if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| { + len_val = dest_len_val; + } + } else if (src_len != .none) { + if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| { + len_val = src_len_val; + } } const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { @@ -22213,6 +22221,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void if (new_src_ptr_ty.isSlice()) { new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); } + } else if (dest_len == .none and len_val == null) { + // Change the dest to a slice, since its type must have the length. + const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); + new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false); } try sema.requireRuntimeBlock(block, src, runtime_src); diff --git a/test/behavior/memcpy.zig b/test/behavior/memcpy.zig index 66657b26c9..a2aad42402 100644 --- a/test/behavior/memcpy.zig +++ b/test/behavior/memcpy.zig @@ -44,3 +44,24 @@ fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void { try expect(buf[98] == 'l'); try expect(buf[99] == 'o'); } + +test "@memcpy dest many pointer" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + try testMemcpyDestManyPtr(); + try comptime testMemcpyDestManyPtr(); +} + +fn testMemcpyDestManyPtr() !void { + var str = "hello".*; + var buf: [5]u8 = undefined; + @memcpy(@ptrCast([*]u8, &buf), @ptrCast([*]const u8, &str)[0..5]); + try expect(buf[0] == 'h'); + try expect(buf[1] == 'e'); + try expect(buf[2] == 'l'); + try expect(buf[3] == 'l'); + try expect(buf[4] == 'o'); +}