mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 14:24:43 +00:00
frontend: comptime array slice-by-length OOB detection
This commit is contained in:
parent
ab22844176
commit
2583b389ea
3 changed files with 45 additions and 11 deletions
37
src/Sema.zig
37
src/Sema.zig
|
|
@ -33285,15 +33285,34 @@ fn analyzeSlice(
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds_check: {
|
bounds_check: {
|
||||||
const actual_len = if (array_ty.zigTypeTag(mod) == .Array)
|
const actual_len = l: {
|
||||||
try mod.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(mod))
|
if (array_ty.zigTypeTag(mod) == .Array) {
|
||||||
else if (slice_ty.isSlice(mod)) l: {
|
const len = array_ty.arrayLenIncludingSentinel(mod);
|
||||||
const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
|
// If the end is comptime-known, we can emit a
|
||||||
break :l if (slice_ty.sentinel(mod) == null)
|
// compile error if it would be out-of-bounds even
|
||||||
slice_len_inst
|
// with a start value of 0.
|
||||||
else
|
if (uncasted_end_opt != .none) {
|
||||||
try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
|
if (try sema.resolveDefinedValue(block, end_src, uncasted_end_opt)) |end_val| {
|
||||||
} else break :bounds_check;
|
const end_int = end_val.getUnsignedInt(mod).?;
|
||||||
|
if (end_int > len) return sema.fail(
|
||||||
|
block,
|
||||||
|
end_src,
|
||||||
|
"slice end index {d} exceeds array length of type '{}'",
|
||||||
|
.{ end_int, array_ty.fmt(mod) },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break :l try mod.intRef(Type.usize, len);
|
||||||
|
}
|
||||||
|
if (slice_ty.isSlice(mod)) {
|
||||||
|
const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
|
||||||
|
break :l if (slice_ty.sentinel(mod) == null)
|
||||||
|
slice_len_inst
|
||||||
|
else
|
||||||
|
try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
|
||||||
|
}
|
||||||
|
break :bounds_check;
|
||||||
|
};
|
||||||
|
|
||||||
const actual_end = if (slice_sentinel != null)
|
const actual_end = if (slice_sentinel != null)
|
||||||
try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
|
try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
export fn b() void {
|
||||||
|
var buf: [5]u8 = undefined;
|
||||||
|
_ = buf[foo(6)..][0..10];
|
||||||
|
return error.TestFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(a: u32) u32 {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :3:26: error: slice end index 10 exceeds array length of type '[5]u8'
|
||||||
|
|
@ -2,14 +2,14 @@ const std = @import("std");
|
||||||
|
|
||||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||||
_ = stack_trace;
|
_ = stack_trace;
|
||||||
if (std.mem.eql(u8, message, "index out of bounds: index 16, len 5")) {
|
if (std.mem.eql(u8, message, "index out of bounds: index 9, len 5")) {
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var buf: [5]u8 = undefined;
|
var buf: [5]u8 = undefined;
|
||||||
_ = buf[foo(6)..][0..10];
|
_ = buf[foo(6)..][0..3];
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
}
|
}
|
||||||
fn foo(a: u32) u32 {
|
fn foo(a: u32) u32 {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue