Commit 91fd0f42c8

Mitchell Hashimoto <mitchell.hashimoto@gmail.com>
2022-03-21 04:04:18
stage2: out of bounds error for slicing
1 parent 0fb005d
Changed files (3)
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);
 
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 {
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",