diff --git a/src/Sema.zig b/src/Sema.zig index e964c8f76b..4bfd6ac1c4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25574,6 +25574,22 @@ fn analyzeSlice( const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true); try sema.addSafetyCheck(block, is_non_null, .unwrap_null); } + + if (slice_ty.isSlice()) { + const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); + const actual_len = if (slice_ty.sentinel() == null) + slice_len_inst + else + try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src); + + const actual_end = if (slice_sentinel != null) + try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src) + else + end; + + try sema.panicIndexOutOfBounds(block, src, actual_end, actual_len, .cmp_lte); + } + // requirement: result[new_len] == slice_sentinel try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len); } @@ -25635,7 +25651,11 @@ fn analyzeSlice( break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src); } else null; if (opt_len_inst) |len_inst| { - try sema.panicIndexOutOfBounds(block, src, end, len_inst, .cmp_lte); + const actual_end = if (slice_sentinel != null) + try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src) + else + end; + try sema.panicIndexOutOfBounds(block, src, actual_end, len_inst, .cmp_lte); } // requirement: start <= end diff --git a/test/cases/safety/cast []u8 to bigger slice of wrong size.zig b/test/cases/safety/cast []u8 to bigger slice of wrong size.zig index 588801b27e..6fddb63bee 100644 --- a/test/cases/safety/cast []u8 to bigger slice of wrong size.zig +++ b/test/cases/safety/cast []u8 to bigger slice of wrong size.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, "exact division produced remainder")) { + std.process.exit(0); + } + std.process.exit(1); } pub fn main() !void { @@ -15,5 +17,5 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { return std.mem.bytesAsSlice(i32, slice); } // run -// backend=stage1 -// target=native \ No newline at end of file +// backend=llvm +// target=native diff --git a/test/cases/safety/empty slice with sentinel out of bounds.zig b/test/cases/safety/empty slice with sentinel out of bounds.zig index ad8010868a..835b084740 100644 --- a/test/cases/safety/empty slice with sentinel out of bounds.zig +++ b/test/cases/safety/empty slice with sentinel out of bounds.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "index out of bounds")) { + if (std.mem.eql(u8, message, "attempt to index out of bound: index 1, len 0")) { std.process.exit(0); } std.process.exit(1); @@ -17,5 +17,5 @@ pub fn main() !void { } // run -// backend=stage1 +// backend=llvm // target=native diff --git a/test/cases/safety/slice with sentinel out of bounds - runtime len.zig b/test/cases/safety/slice with sentinel out of bounds - runtime len.zig new file mode 100644 index 0000000000..fa2e127107 --- /dev/null +++ b/test/cases/safety/slice with sentinel out of bounds - runtime len.zig @@ -0,0 +1,22 @@ +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 index out of bound: index 5, len 4")) { + std.process.exit(0); + } + std.process.exit(1); +} + +pub fn main() !void { + var buf = [4]u8{ 'a', 'b', 'c', 0 }; + const input: []u8 = &buf; + var len: usize = 4; + const slice = input[0..len :0]; + _ = slice; + return error.TestFailed; +} + +// run +// backend=llvm +// target=native diff --git a/test/cases/safety/slice with sentinel out of bounds.zig b/test/cases/safety/slice with sentinel out of bounds.zig index 1ca83ea481..3cc8bfb355 100644 --- a/test/cases/safety/slice with sentinel out of bounds.zig +++ b/test/cases/safety/slice with sentinel out of bounds.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "index out of bounds")) { + if (std.mem.eql(u8, message, "attempt to index out of bound: index 5, len 4")) { std.process.exit(0); } std.process.exit(1); @@ -17,5 +17,5 @@ pub fn main() !void { } // run -// backend=stage1 +// backend=llvm // target=native