| author | |
| committer | |
| log | 4d5e0a0434a69059f623e5c51862fb1a2c553abc |
| tree | 359645e37191ea162492f9814885d720421d52d2 |
| parent | 7741aca96c8cc6df7e8c4bd10ada741d6a3ffb9d |
When the slice-by-length start position is runtime-known, it is likely
protected by a runtime-known condition and therefore a compile error is
less appropriate than a runtime panic check.
This is demonstrated in the json code that was updated and then reverted
in this commit.
When #3806 is implemented, this decision can be reassessed.
Revert "std: work around compiler unable to evaluate condition at compile time"
Revert "frontend: comptime array slice-by-length OOB detection"
This reverts commit 7741aca96c8cc6df7e8c4bd10ada741d6a3ffb9d.
This reverts commit 2583b389eaf5f7aaa0eb79b51126506c1e172d15.4 files changed, 28 insertions(+), 58 deletions(-)
lib/std/json/static.zig+17-13| ... | ... | @@ -400,20 +400,24 @@ pub fn innerParse( |
| 400 | 400 | @memcpy(r[i..][0..slice.len], slice); |
| 401 | 401 | i += slice.len; |
| 402 | 402 | }, |
| 403 | inline .partial_string_escaped_1, | |
| 404 | .partial_string_escaped_2, | |
| 405 | .partial_string_escaped_3, | |
| 406 | .partial_string_escaped_4, | |
| 407 | => |arr| { | |
| 403 | .partial_string_escaped_1 => |arr| { | |
| 408 | 404 | if (i + arr.len > r.len) return error.LengthMismatch; |
| 409 | ||
| 410 | // Implementing https://github.com/ziglang/zig/issues/3806 | |
| 411 | // would make this no longer needed because the | |
| 412 | // above condition would become compile-time | |
| 413 | // known. | |
| 414 | if (arr.len > r.len) unreachable; | |
| 415 | ||
| 416 | @memcpy(r[i..][0..arr.len], &arr); | |
| 405 | @memcpy(r[i..][0..arr.len], arr[0..]); | |
| 406 | i += arr.len; | |
| 407 | }, | |
| 408 | .partial_string_escaped_2 => |arr| { | |
| 409 | if (i + arr.len > r.len) return error.LengthMismatch; | |
| 410 | @memcpy(r[i..][0..arr.len], arr[0..]); | |
| 411 | i += arr.len; | |
| 412 | }, | |
| 413 | .partial_string_escaped_3 => |arr| { | |
| 414 | if (i + arr.len > r.len) return error.LengthMismatch; | |
| 415 | @memcpy(r[i..][0..arr.len], arr[0..]); | |
| 416 | i += arr.len; | |
| 417 | }, | |
| 418 | .partial_string_escaped_4 => |arr| { | |
| 419 | if (i + arr.len > r.len) return error.LengthMismatch; | |
| 420 | @memcpy(r[i..][0..arr.len], arr[0..]); | |
| 417 | 421 | i += arr.len; |
| 418 | 422 | }, |
| 419 | 423 | else => unreachable, |
src/Sema.zig+9-28| ... | ... | @@ -33285,34 +33285,15 @@ fn analyzeSlice( |
| 33285 | 33285 | } |
| 33286 | 33286 | |
| 33287 | 33287 | bounds_check: { |
| 33288 | const actual_len = l: { | |
| 33289 | if (array_ty.zigTypeTag(mod) == .Array) { | |
| 33290 | const len = array_ty.arrayLenIncludingSentinel(mod); | |
| 33291 | // If the end is comptime-known, we can emit a | |
| 33292 | // compile error if it would be out-of-bounds even | |
| 33293 | // with a start value of 0. | |
| 33294 | if (uncasted_end_opt != .none) { | |
| 33295 | if (try sema.resolveDefinedValue(block, end_src, uncasted_end_opt)) |end_val| { | |
| 33296 | const end_int = end_val.getUnsignedInt(mod).?; | |
| 33297 | if (end_int > len) return sema.fail( | |
| 33298 | block, | |
| 33299 | end_src, | |
| 33300 | "slice end index {d} exceeds array length of type '{}'", | |
| 33301 | .{ end_int, array_ty.fmt(mod) }, | |
| 33302 | ); | |
| 33303 | } | |
| 33304 | } | |
| 33305 | break :l try mod.intRef(Type.usize, len); | |
| 33306 | } | |
| 33307 | if (slice_ty.isSlice(mod)) { | |
| 33308 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); | |
| 33309 | break :l if (slice_ty.sentinel(mod) == null) | |
| 33310 | slice_len_inst | |
| 33311 | else | |
| 33312 | try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true); | |
| 33313 | } | |
| 33314 | break :bounds_check; | |
| 33315 | }; | |
| 33288 | const actual_len = if (array_ty.zigTypeTag(mod) == .Array) | |
| 33289 | try mod.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(mod)) | |
| 33290 | else if (slice_ty.isSlice(mod)) l: { | |
| 33291 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); | |
| 33292 | break :l if (slice_ty.sentinel(mod) == null) | |
| 33293 | slice_len_inst | |
| 33294 | else | |
| 33295 | try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true); | |
| 33296 | } else break :bounds_check; | |
| 33316 | 33297 | |
| 33317 | 33298 | const actual_end = if (slice_sentinel != null) |
| 33318 | 33299 | try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true) |
test/cases/compile_errors/out of bounds array slice by length.zig	 deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | export fn b() void { | |
| 2 | var buf: [5]u8 = undefined; | |
| 3 | _ = buf[foo(6)..][0..10]; | |
| 4 | return error.TestFailed; | |
| 5 | } | |
| 6 | ||
| 7 | fn foo(a: u32) u32 { | |
| 8 | return a; | |
| 9 | } | |
| 10 | ||
| 11 | // error | |
| 12 | // backend=stage2 | |
| 13 | // target=native | |
| 14 | // | |
| 15 | // :3:26: error: slice end index 10 exceeds array length of type '[5]u8' |
test/cases/safety/out of bounds array slice by length.zig	+2-2| ... | ... | @@ -2,14 +2,14 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "index out of bounds: index 9, len 5")) { | |
| 5 | if (std.mem.eql(u8, message, "index out of bounds: index 16, len 5")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
| 9 | 9 | } |
| 10 | 10 | pub fn main() !void { |
| 11 | 11 | var buf: [5]u8 = undefined; |
| 12 | _ = buf[foo(6)..][0..3]; | |
| 12 | _ = buf[foo(6)..][0..10]; | |
| 13 | 13 | return error.TestFailed; |
| 14 | 14 | } |
| 15 | 15 | fn foo(a: u32) u32 { |