| author | |
| committer | |
| log | 1ba72bcf9a86060fc39117f89536a971ace620c4 |
| tree | 0c4b819a94bdc1692a17d4a0e542505d1f9c0b6e |
| parent | 747f58366a25593431a0e8ff85d76095e0e39e74 |
11 files changed, 137 insertions(+), 28 deletions(-)
lib/std/zig/c_builtins.zig+4-4| ... | ... | @@ -171,10 +171,10 @@ pub inline fn __builtin_memcpy( |
| 171 | 171 | noalias src: ?*const anyopaque, |
| 172 | 172 | len: usize, |
| 173 | 173 | ) ?*anyopaque { |
| 174 | const dst_cast = @ptrCast([*c]u8, dst); | |
| 175 | const src_cast = @ptrCast([*c]const u8, src); | |
| 176 | ||
| 177 | @memcpy(dst_cast[0..len], src_cast); | |
| 174 | if (len > 0) @memcpy( | |
| 175 | @ptrCast([*]u8, dst.?)[0..len], | |
| 176 | @ptrCast([*]const u8, src.?), | |
| 177 | ); | |
| 178 | 178 | return dst; |
| 179 | 179 | } |
| 180 | 180 |
src/Sema.zig+1-17| ... | ... | @@ -20424,22 +20424,6 @@ fn checkPtrType( |
| 20424 | 20424 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); |
| 20425 | 20425 | } |
| 20426 | 20426 | |
| 20427 | fn checkSliceOrArrayType( | |
| 20428 | sema: *Sema, | |
| 20429 | block: *Block, | |
| 20430 | ty_src: LazySrcLoc, | |
| 20431 | ty: Type, | |
| 20432 | ) CompileError!void { | |
| 20433 | if (ty.zigTypeTag() == .Pointer) { | |
| 20434 | switch (ty.ptrSize()) { | |
| 20435 | .Slice => return, | |
| 20436 | .One => if (ty.childType().zigTypeTag() == .Array) return, | |
| 20437 | else => {}, | |
| 20438 | } | |
| 20439 | } | |
| 20440 | return sema.fail(block, ty_src, "expected slice or array pointer; found '{}'", .{ty.fmt(sema.mod)}); | |
| 20441 | } | |
| 20442 | ||
| 20443 | 20427 | fn checkVectorElemType( |
| 20444 | 20428 | sema: *Sema, |
| 20445 | 20429 | block: *Block, |
| ... | ... | @@ -21993,7 +21977,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 21993 | 21977 | const dest_ptr = try sema.resolveInst(extra.lhs); |
| 21994 | 21978 | const uncoerced_elem = try sema.resolveInst(extra.rhs); |
| 21995 | 21979 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 21996 | try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty); | |
| 21980 | try checkIndexable(sema, block, dest_src, dest_ptr_ty); | |
| 21997 | 21981 | |
| 21998 | 21982 | const dest_elem_ty = dest_ptr_ty.elemType2(); |
| 21999 | 21983 | const target = sema.mod.getTarget(); |
test/behavior/builtin_functions_returning_void_or_noreturn.zig+2-2| ... | ... | @@ -17,8 +17,8 @@ test { |
| 17 | 17 | try testing.expectEqual(void, @TypeOf(@breakpoint())); |
| 18 | 18 | try testing.expectEqual({}, @export(x, .{ .name = "x" })); |
| 19 | 19 | try testing.expectEqual({}, @fence(.Acquire)); |
| 20 | try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1), @intToPtr([*]u8, 1), 0)); | |
| 21 | try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1), undefined, 0)); | |
| 20 | try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1)[0..0], @intToPtr([*]u8, 1)[0..0])); | |
| 21 | try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1)[0..0], undefined)); | |
| 22 | 22 | try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {})); |
| 23 | 23 | try testing.expectEqual({}, @prefetch(&val, .{})); |
| 24 | 24 | try testing.expectEqual({}, @setAlignStack(16)); |
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+21-4| ... | ... | @@ -2,18 +2,35 @@ pub export fn entry() void { |
| 2 | 2 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; |
| 3 | 3 | var slice: []u8 = &buf; |
| 4 | 4 | const a: u32 = 1234; |
| 5 | @memcpy(slice, @ptrCast([*]const u8, &a)); | |
| 5 | @memcpy(slice.ptr, @ptrCast([*]const u8, &a)); | |
| 6 | 6 | } |
| 7 | 7 | pub export fn entry1() void { |
| 8 | 8 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; |
| 9 | 9 | var ptr: *u8 = &buf[0]; |
| 10 | 10 | @memcpy(ptr, 0); |
| 11 | 11 | } |
| 12 | pub export fn entry2() void { | |
| 13 | var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; | |
| 14 | var ptr: *u8 = &buf[0]; | |
| 15 | @memset(ptr, 0); | |
| 16 | } | |
| 17 | pub export fn non_matching_lengths() void { | |
| 18 | var buf1: [5]u8 = .{ 1, 2, 3, 4, 5 }; | |
| 19 | var buf2: [6]u8 = .{ 1, 2, 3, 4, 5, 6 }; | |
| 20 | @memcpy(&buf2, &buf1); | |
| 21 | } | |
| 12 | 22 | |
| 13 | 23 | // error |
| 14 | 24 | // backend=stage2 |
| 15 | 25 | // target=native |
| 16 | 26 | // |
| 17 | // :5:13: error: expected type '[*]u8', found '[]u8' | |
| 18 | // :10:13: error: expected type '[*]u8', found '*u8' | |
| 19 | // :10:13: note: a single pointer cannot cast into a many pointer | |
| 27 | // :5:5: error: unknown @memcpy length | |
| 28 | // :5:18: note: destination type [*]u8 provides no length | |
| 29 | // :5:24: note: source type [*]align(4) const u8 provides no length | |
| 30 | // :10:13: error: type 'u8' does not support indexing | |
| 31 | // :10:13: note: for loop operand must be an array, slice, tuple, or vector | |
| 32 | // :15:13: error: type '*u8' does not support indexing | |
| 33 | // :15:13: note: for loop operand must be an array, slice, tuple, or vector | |
| 34 | // :20:5: error: non-matching @memcpy lengths | |
| 35 | // :20:13: note: length 6 here | |
| 36 | // :20:20: note: length 5 here |
test/cases/safety/memcpy_alias.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "@memcpy arguments alias")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [2]u8{ 1, 2 } ** 5; | |
| 12 | var len: usize = 5; | |
| 13 | @memcpy(buffer[0..len], buffer[4 .. 4 + len]); | |
| 14 | } | |
| 15 | // run | |
| 16 | // backend=llvm | |
| 17 | // target=native |
test/cases/safety/memcpy_len_mismatch.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "@memcpy arguments have non-equal lengths")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [2]u8{ 1, 2 } ** 5; | |
| 12 | var len: usize = 5; | |
| 13 | @memcpy(buffer[0..len], buffer[len .. len + 4]); | |
| 14 | } | |
| 15 | // run | |
| 16 | // backend=llvm | |
| 17 | // target=native |
test/cases/safety/memset_array_undefined_bytes.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "integer overflow")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 }; | |
| 12 | @memset(&buffer, undefined); | |
| 13 | var x: u8 = buffer[1]; | |
| 14 | x += buffer[2]; | |
| 15 | } | |
| 16 | // run | |
| 17 | // backend=llvm | |
| 18 | // target=native |
test/cases/safety/memset_array_undefined_large.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "integer overflow")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 }; | |
| 12 | @memset(&buffer, undefined); | |
| 13 | var x: i32 = buffer[1]; | |
| 14 | x += buffer[2]; | |
| 15 | } | |
| 16 | // run | |
| 17 | // backend=llvm | |
| 18 | // target=native |
test/cases/safety/memset_slice_undefined_bytes.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "integer overflow")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 }; | |
| 12 | var len = buffer.len; | |
| 13 | @memset(buffer[0..len], undefined); | |
| 14 | var x: u8 = buffer[1]; | |
| 15 | x += buffer[2]; | |
| 16 | } | |
| 17 | // run | |
| 18 | // backend=llvm | |
| 19 | // target=native |
test/cases/safety/memset_slice_undefined_large.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 4 | _ = stack_trace; | |
| 5 | if (std.mem.eql(u8, message, "integer overflow")) { | |
| 6 | std.process.exit(0); | |
| 7 | } | |
| 8 | std.process.exit(1); | |
| 9 | } | |
| 10 | pub fn main() !void { | |
| 11 | var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 }; | |
| 12 | var len = buffer.len; | |
| 13 | @memset(buffer[0..len], undefined); | |
| 14 | var x: i32 = buffer[1]; | |
| 15 | x += buffer[2]; | |
| 16 | } | |
| 17 | // run | |
| 18 | // backend=llvm | |
| 19 | // target=native |
test/cases/safety/switch on corrupted union value.zig	+1-1| ... | ... | @@ -15,7 +15,7 @@ const U = union(enum(u32)) { |
| 15 | 15 | |
| 16 | 16 | pub fn main() !void { |
| 17 | 17 | var u: U = undefined; |
| 18 | @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U)); | |
| 18 | @memset(@ptrCast([*]u8, &u)[0..@sizeOf(U)], 0x55); | |
| 19 | 19 | switch (u) { |
| 20 | 20 | .X, .Y => @breakpoint(), |
| 21 | 21 | } |