From 91fd0f42c88f4bea424b5a5c58435a2a98b57a58 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 20 Mar 2022 20:04:18 -0700 Subject: [PATCH] stage2: out of bounds error for slicing --- src/Sema.zig | 30 ++++++++++++++++++++++++++++++ test/behavior/cast.zig | 6 +++++- test/compile_errors.zig | 23 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/Sema.zig b/src/Sema.zig index 61c46bcce7..2a3eff928b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -19587,6 +19587,14 @@ fn analyzeSlice( if (!end_is_len) { const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); if (try sema.resolveMaybeUndefVal(block, end_src, end)) |end_val| { + if (end_val.compare(.gt, len_val, Type.usize)) { + return sema.fail( + block, + end_src, + "end index {} out of bounds for array of length {}", + .{ end_val.fmtValue(Type.usize), len_val.fmtValue(Type.usize) }, + ); + } if (end_val.eql(len_val, Type.usize)) { end_is_len = true; } @@ -19605,6 +19613,14 @@ fn analyzeSlice( .data = slice_val.sliceLen(), }; const slice_len_val = Value.initPayload(&int_payload.base); + if (end_val.compare(.gt, slice_len_val, Type.usize)) { + return sema.fail( + block, + end_src, + "end index {} out of bounds for slice of length {}", + .{ end_val.fmtValue(Type.usize), slice_len_val.fmtValue(Type.usize) }, + ); + } if (end_val.eql(slice_len_val, Type.usize)) { end_is_len = true; } @@ -19635,6 +19651,20 @@ fn analyzeSlice( break :s null; }; + // requirement: start <= end + if (try sema.resolveDefinedValue(block, src, end)) |end_val| { + if (try sema.resolveDefinedValue(block, src, start)) |start_val| { + if (start_val.compare(.gt, end_val, Type.usize)) { + return sema.fail( + block, + start_src, + "start index {} is larger than end index {}", + .{ start_val.fmtValue(Type.usize), end_val.fmtValue(Type.usize) }, + ); + } + } + } + const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src); const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 4e2b5dad7b..061a8219b8 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -906,7 +906,11 @@ test "peer cast [*:x]T to [*]T" { } test "peer cast [:x]T to [*:x]T" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 81083cb049..c479dd9c88 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -21,6 +21,29 @@ pub fn addCases(ctx: *TestContext) !void { , &[_][]const u8{ ":2:20: error: import of file outside package path: '../../above.zig'", }); + + case.addError( + \\comptime { + \\ var array = [_:0]u8{ 1, 2, 3, 4 }; + \\ var src_slice: [:0]u8 = &array; + \\ var slice = src_slice[2..5]; + \\ _ = slice; + \\} + \\comptime { + \\ var array = [_:0]u8{ 1, 2, 3, 4 }; + \\ var slice = array[2..5]; + \\ _ = slice; + \\} + \\comptime { + \\ var array = [_:0]u8{ 1, 2, 3, 4 }; + \\ var slice = array[3..2]; + \\ _ = slice; + \\} + , &[_][]const u8{ + ":4:26: error: end index 5 out of bounds for slice of length 4", + ":9:22: error: end index 5 out of bounds for array of length 4", + ":14:22: error: start index 3 is larger than end index 2", + }); } ctx.objErrStage1("exported enum without explicit integer tag type",