authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-01-02 17:37:21+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-02 17:37:21+02:00
logd9d840a33ac8abb0e616de862f592821a7f4a35e
treedd17b4f37cf2b08816af8a99159e5630c6268b35
parenta04d4330945565b8d6f298ace993f6954c42d0f3
parent41d5aa1b365516c5f1bad63bfa3bdd7ad0ba6842
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #18410 from dweiller/by-length-slice-bug

sema: add compile error for OOB by-length slice of array

4 files changed, 76 insertions(+), 0 deletions(-)

lib/std/json/static.zig+12
......@@ -402,21 +402,33 @@ pub fn innerParse(
402402 },
403403 .partial_string_escaped_1 => |arr| {
404404 if (i + arr.len > r.len) return error.LengthMismatch;
405 // tell the compiler that the by-length slice below is valid;
406 // this assert is required for the inequality to be comptime-known
407 if (arr.len > r.len) unreachable;
405408 @memcpy(r[i..][0..arr.len], arr[0..]);
406409 i += arr.len;
407410 },
408411 .partial_string_escaped_2 => |arr| {
409412 if (i + arr.len > r.len) return error.LengthMismatch;
413 // tell the compiler that the by-length slice below is valid;
414 // this assert is required for the inequality to be comptime-known
415 if (arr.len > r.len) unreachable;
410416 @memcpy(r[i..][0..arr.len], arr[0..]);
411417 i += arr.len;
412418 },
413419 .partial_string_escaped_3 => |arr| {
414420 if (i + arr.len > r.len) return error.LengthMismatch;
421 // tell the compiler that the by-length slice below is valid;
422 // this assert is required for the inequality to be comptime-known
423 if (arr.len > r.len) unreachable;
415424 @memcpy(r[i..][0..arr.len], arr[0..]);
416425 i += arr.len;
417426 },
418427 .partial_string_escaped_4 => |arr| {
419428 if (i + arr.len > r.len) return error.LengthMismatch;
429 // tell the compiler that the by-length slice below is valid;
430 // this assert is required for the inequality to be comptime-known
431 if (arr.len > r.len) unreachable;
420432 @memcpy(r[i..][0..arr.len], arr[0..]);
421433 i += arr.len;
422434 },
src/Sema.zig+24
......@@ -32160,6 +32160,30 @@ fn analyzeSlice(
3216032160 if (!end_is_len) {
3216132161 const end = if (by_length) end: {
3216232162 const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
32163 if (try sema.resolveValue(len)) |slice_len_val| {
32164 const len_s_val = try mod.intValue(
32165 Type.usize,
32166 array_ty.arrayLenIncludingSentinel(mod),
32167 );
32168 if (!(try sema.compareScalar(slice_len_val, .lte, len_s_val, Type.usize))) {
32169 const sentinel_label: []const u8 = if (array_ty.sentinel(mod) != null)
32170 " +1 (sentinel)"
32171 else
32172 "";
32173
32174 return sema.fail(
32175 block,
32176 end_src,
32177 "length {} out of bounds for array of length {}{s}",
32178 .{
32179 slice_len_val.fmtValue(Type.usize, mod),
32180 len_val.fmtValue(Type.usize, mod),
32181 sentinel_label,
32182 },
32183 );
32184 }
32185 }
32186 // check len is less than array size if comptime known
3216332187 const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
3216432188 break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
3216532189 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
test/cases/compile_errors/slice_of_array_by-length_oversized.zig created+19
......@@ -0,0 +1,19 @@
1export fn entry1() void {
2 var buf: [5]u8 = undefined;
3 var a: u32 = 6;
4 _ = &a;
5 _ = buf[a..][0..10];
6}
7
8export fn entry2() void {
9 var buf: [5]u8 = undefined;
10 const a: u32 = 6;
11 _ = buf[a..][0..10];
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :5:21: error: length 10 out of bounds for array of length 5
19// :11:21: error: length 10 out of bounds for array of length 5
test/cases/safety/array slice by-length oversized.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "index out of bounds: index 12, len 5")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11pub fn main() !void {
12 var buf: [5]u8 = undefined;
13 var a: u32 = 6;
14 _ = &a;
15 _ = buf[a..][0..a];
16 return error.TestFailed;
17}
18
19// run
20// backend=llvm
21// target=native