mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #18410 from dweiller/by-length-slice-bug
sema: add compile error for OOB by-length slice of array
This commit is contained in:
commit
d9d840a33a
@ -402,21 +402,33 @@ pub fn innerParse(
|
||||
},
|
||||
.partial_string_escaped_1 => |arr| {
|
||||
if (i + arr.len > r.len) return error.LengthMismatch;
|
||||
// tell the compiler that the by-length slice below is valid;
|
||||
// this assert is required for the inequality to be comptime-known
|
||||
if (arr.len > r.len) unreachable;
|
||||
@memcpy(r[i..][0..arr.len], arr[0..]);
|
||||
i += arr.len;
|
||||
},
|
||||
.partial_string_escaped_2 => |arr| {
|
||||
if (i + arr.len > r.len) return error.LengthMismatch;
|
||||
// tell the compiler that the by-length slice below is valid;
|
||||
// this assert is required for the inequality to be comptime-known
|
||||
if (arr.len > r.len) unreachable;
|
||||
@memcpy(r[i..][0..arr.len], arr[0..]);
|
||||
i += arr.len;
|
||||
},
|
||||
.partial_string_escaped_3 => |arr| {
|
||||
if (i + arr.len > r.len) return error.LengthMismatch;
|
||||
// tell the compiler that the by-length slice below is valid;
|
||||
// this assert is required for the inequality to be comptime-known
|
||||
if (arr.len > r.len) unreachable;
|
||||
@memcpy(r[i..][0..arr.len], arr[0..]);
|
||||
i += arr.len;
|
||||
},
|
||||
.partial_string_escaped_4 => |arr| {
|
||||
if (i + arr.len > r.len) return error.LengthMismatch;
|
||||
// tell the compiler that the by-length slice below is valid;
|
||||
// this assert is required for the inequality to be comptime-known
|
||||
if (arr.len > r.len) unreachable;
|
||||
@memcpy(r[i..][0..arr.len], arr[0..]);
|
||||
i += arr.len;
|
||||
},
|
||||
|
||||
24
src/Sema.zig
24
src/Sema.zig
@ -32160,6 +32160,30 @@ fn analyzeSlice(
|
||||
if (!end_is_len) {
|
||||
const end = if (by_length) end: {
|
||||
const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
|
||||
if (try sema.resolveValue(len)) |slice_len_val| {
|
||||
const len_s_val = try mod.intValue(
|
||||
Type.usize,
|
||||
array_ty.arrayLenIncludingSentinel(mod),
|
||||
);
|
||||
if (!(try sema.compareScalar(slice_len_val, .lte, len_s_val, Type.usize))) {
|
||||
const sentinel_label: []const u8 = if (array_ty.sentinel(mod) != null)
|
||||
" +1 (sentinel)"
|
||||
else
|
||||
"";
|
||||
|
||||
return sema.fail(
|
||||
block,
|
||||
end_src,
|
||||
"length {} out of bounds for array of length {}{s}",
|
||||
.{
|
||||
slice_len_val.fmtValue(Type.usize, mod),
|
||||
len_val.fmtValue(Type.usize, mod),
|
||||
sentinel_label,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
// check len is less than array size if comptime known
|
||||
const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
|
||||
break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
|
||||
} else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
export fn entry1() void {
|
||||
var buf: [5]u8 = undefined;
|
||||
var a: u32 = 6;
|
||||
_ = &a;
|
||||
_ = buf[a..][0..10];
|
||||
}
|
||||
|
||||
export fn entry2() void {
|
||||
var buf: [5]u8 = undefined;
|
||||
const a: u32 = 6;
|
||||
_ = buf[a..][0..10];
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:21: error: length 10 out of bounds for array of length 5
|
||||
// :11:21: error: length 10 out of bounds for array of length 5
|
||||
21
test/cases/safety/array slice by-length oversized.zig
Normal file
21
test/cases/safety/array slice by-length oversized.zig
Normal file
@ -0,0 +1,21 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = stack_trace;
|
||||
if (std.mem.eql(u8, message, "index out of bounds: index 12, len 5")) {
|
||||
std.process.exit(0);
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var buf: [5]u8 = undefined;
|
||||
var a: u32 = 6;
|
||||
_ = &a;
|
||||
_ = buf[a..][0..a];
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
// run
|
||||
// backend=llvm
|
||||
// target=native
|
||||
Loading…
x
Reference in New Issue
Block a user