| author | |
| committer | |
| log | d9d840a33ac8abb0e616de862f592821a7f4a35e |
| tree | dd17b4f37cf2b08816af8a99159e5630c6268b35 |
| parent | a04d4330945565b8d6f298ace993f6954c42d0f3 |
| parent | 41d5aa1b365516c5f1bad63bfa3bdd7ad0ba6842 |
| signature |
sema: add compile error for OOB by-length slice of array4 files changed, 76 insertions(+), 0 deletions(-)
lib/std/json/static.zig+12| ... | ... | @@ -402,21 +402,33 @@ pub fn innerParse( |
| 402 | 402 | }, |
| 403 | 403 | .partial_string_escaped_1 => |arr| { |
| 404 | 404 | 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; | |
| 405 | 408 | @memcpy(r[i..][0..arr.len], arr[0..]); |
| 406 | 409 | i += arr.len; |
| 407 | 410 | }, |
| 408 | 411 | .partial_string_escaped_2 => |arr| { |
| 409 | 412 | 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; | |
| 410 | 416 | @memcpy(r[i..][0..arr.len], arr[0..]); |
| 411 | 417 | i += arr.len; |
| 412 | 418 | }, |
| 413 | 419 | .partial_string_escaped_3 => |arr| { |
| 414 | 420 | 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; | |
| 415 | 424 | @memcpy(r[i..][0..arr.len], arr[0..]); |
| 416 | 425 | i += arr.len; |
| 417 | 426 | }, |
| 418 | 427 | .partial_string_escaped_4 => |arr| { |
| 419 | 428 | 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; | |
| 420 | 432 | @memcpy(r[i..][0..arr.len], arr[0..]); |
| 421 | 433 | i += arr.len; |
| 422 | 434 | }, |
src/Sema.zig+24| ... | ... | @@ -32160,6 +32160,30 @@ fn analyzeSlice( |
| 32160 | 32160 | if (!end_is_len) { |
| 32161 | 32161 | const end = if (by_length) end: { |
| 32162 | 32162 | 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 | |
| 32163 | 32187 | const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false); |
| 32164 | 32188 | break :end try sema.coerce(block, Type.usize, uncasted_end, end_src); |
| 32165 | 32189 | } 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 @@ |
| 1 | export fn entry1() void { | |
| 2 | var buf: [5]u8 = undefined; | |
| 3 | var a: u32 = 6; | |
| 4 | _ = &a; | |
| 5 | _ = buf[a..][0..10]; | |
| 6 | } | |
| 7 | ||
| 8 | export 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 11 | pub 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 |