Sema: account for sentinel in bounds check

This commit is contained in:
Veikka Tuominen
2022-08-05 17:08:31 +03:00
parent 6aa438f065
commit 5605f6e0e3
5 changed files with 53 additions and 9 deletions

View File

@@ -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

View File

@@ -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
// backend=llvm
// target=native

View File

@@ -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

View File

@@ -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

View File

@@ -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