diff --git a/src/Sema.zig b/src/Sema.zig index d81d2fa726..e964c8f76b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25569,6 +25569,11 @@ fn analyzeSlice( const new_ptr_val = opt_new_ptr_val orelse { const result = try block.addBitCast(return_ty, new_ptr); if (block.wantSafety()) { + // requirement: slicing C ptr is non-null + if (ptr_ptr_child_ty.isCPtr()) { + const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true); + try sema.addSafetyCheck(block, is_non_null, .unwrap_null); + } // requirement: result[new_len] == slice_sentinel try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len); } diff --git a/test/cases/safety/pointer slice sentinel mismatch.zig b/test/cases/safety/pointer slice sentinel mismatch.zig index f79e2a860c..ec25ec2969 100644 --- a/test/cases/safety/pointer slice sentinel mismatch.zig +++ b/test/cases/safety/pointer slice sentinel mismatch.zig @@ -2,14 +2,14 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "sentinel mismatch")) { + if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) { std.process.exit(0); } std.process.exit(1); } pub fn main() !void { - var buf: [4]u8 = undefined; + var buf: [4]u8 = .{ 1, 2, 3, 4 }; const ptr: [*]u8 = &buf; const slice = ptr[0..3 :0]; _ = slice; @@ -17,5 +17,5 @@ pub fn main() !void { } // run -// backend=stage1 +// backend=llvm // target=native diff --git a/test/cases/safety/slice sentinel mismatch - floats.zig b/test/cases/safety/slice sentinel mismatch - floats.zig index 3295c20db3..3d08872ca7 100644 --- a/test/cases/safety/slice sentinel mismatch - floats.zig +++ b/test/cases/safety/slice sentinel mismatch - floats.zig @@ -2,19 +2,19 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "sentinel mismatch")) { + if (std.mem.eql(u8, message, "sentinel mismatch: expected 1.20000004e+00, found 4.0e+00")) { std.process.exit(0); } std.process.exit(1); } pub fn main() !void { - var buf: [4]f32 = undefined; + var buf: [4]f32 = .{ 1, 2, 3, 4 }; const slice = buf[0..3 :1.2]; _ = slice; return error.TestFailed; } // run -// backend=stage1 +// backend=llvm // target=native diff --git a/test/cases/safety/slice sentinel mismatch - optional pointers.zig b/test/cases/safety/slice sentinel mismatch - optional pointers.zig index ecb82c61d4..fbc6fcf428 100644 --- a/test/cases/safety/slice sentinel mismatch - optional pointers.zig +++ b/test/cases/safety/slice sentinel mismatch - optional pointers.zig @@ -2,19 +2,19 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "sentinel mismatch")) { + if (std.mem.eql(u8, message, "sentinel mismatch: expected null, found i32@10")) { std.process.exit(0); } std.process.exit(1); } pub fn main() !void { - var buf: [4]?*i32 = undefined; + var buf: [4]?*i32 = .{ @intToPtr(*i32, 4), @intToPtr(*i32, 8), @intToPtr(*i32, 12), @intToPtr(*i32, 16) }; const slice = buf[0..3 :null]; _ = slice; return error.TestFailed; } // run -// backend=stage1 +// backend=llvm // target=native diff --git a/test/cases/safety/slice slice sentinel mismatch.zig b/test/cases/safety/slice slice sentinel mismatch.zig index 13b331a0f4..b1bca1a11f 100644 --- a/test/cases/safety/slice slice sentinel mismatch.zig +++ b/test/cases/safety/slice slice sentinel mismatch.zig @@ -2,18 +2,18 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "sentinel mismatch")) { + if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) { std.process.exit(0); } std.process.exit(1); } pub fn main() !void { - var buf: [4]u8 = undefined; + var buf: [4]u8 = .{ 1, 2, 3, 4 }; const slice = buf[0..]; const slice2 = slice[0..3 :0]; _ = slice2; return error.TestFailed; } // run -// backend=stage1 +// backend=llvm // target=native diff --git a/test/cases/safety/slicing null C pointer runtime len.zig b/test/cases/safety/slicing null C pointer runtime len.zig new file mode 100644 index 0000000000..e45f9855a7 --- /dev/null +++ b/test/cases/safety/slicing null C pointer runtime len.zig @@ -0,0 +1,20 @@ +const std = @import("std"); + +pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { + _ = stack_trace; + if (std.mem.eql(u8, message, "attempt to use null value")) { + std.process.exit(0); + } + std.process.exit(1); +} + +pub fn main() !void { + var ptr: [*c]const u32 = null; + var len: usize = 3; + var slice = ptr[0..len]; + _ = slice; + return error.TestFailed; +} +// run +// backend=llvm +// target=native \ No newline at end of file diff --git a/test/cases/safety/slicing null C pointer.zig b/test/cases/safety/slicing null C pointer.zig index db8d235c45..1a77d85924 100644 --- a/test/cases/safety/slicing null C pointer.zig +++ b/test/cases/safety/slicing null C pointer.zig @@ -1,9 +1,11 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { - _ = message; _ = stack_trace; - std.process.exit(0); + if (std.mem.eql(u8, message, "attempt to use null value")) { + std.process.exit(0); + } + std.process.exit(1); } pub fn main() !void { @@ -13,5 +15,5 @@ pub fn main() !void { return error.TestFailed; } // run -// backend=stage1 +// backend=llvm // target=native \ No newline at end of file