Commit 1748511058

dweiller <4678790+dweiller@users.noreply.github.com>
2023-12-30 04:37:35
sema: add compile error for OOB by-length slice of array
1 parent 4129996
Changed files (3)
src/Sema.zig
@@ -32160,6 +32160,30 @@ fn analyzeSlice(
             if (!end_is_len) {
                 const end = if (by_length) end: {
                     const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
+                    if (try sema.resolveValue(len)) |slice_len_val| {
+                        const len_s_val = try mod.intValue(
+                            Type.usize,
+                            array_ty.arrayLenIncludingSentinel(mod),
+                        );
+                        if (!(try sema.compareScalar(slice_len_val, .lte, len_s_val, Type.usize))) {
+                            const sentinel_label: []const u8 = if (array_ty.sentinel(mod) != null)
+                                " +1 (sentinel)"
+                            else
+                                "";
+
+                            return sema.fail(
+                                block,
+                                end_src,
+                                "length {} out of bounds for array of length {}{s}",
+                                .{
+                                    slice_len_val.fmtValue(Type.usize, mod),
+                                    len_val.fmtValue(Type.usize, mod),
+                                    sentinel_label,
+                                },
+                            );
+                        }
+                    }
+                    // check len is less than array size if comptime known
                     const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false);
                     break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
                 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
test/cases/compile_errors/slice_of_array_by-length_oversized.zig
@@ -0,0 +1,19 @@
+export fn entry1() void {
+    var buf: [5]u8 = undefined;
+    var a: u32 = 6;
+    _ = &a;
+    _ = buf[a..][0..10];
+}
+
+export fn entry2() void {
+    var buf: [5]u8 = undefined;
+    const a: u32 = 6;
+    _ = buf[a..][0..10];
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :5:21: error: length 10 out of bounds for array of length 5
+// :11:21: error: length 10 out of bounds for array of length 5
test/cases/safety/array slice by-length oversized.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "index out of bounds: index 12, len 5")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf: [5]u8 = undefined;
+    var a: u32 = 6;
+    _ = &a;
+    _ = buf[a..][0..a];
+    return error.TestFailed;
+}
+
+// run
+// backend=llvm
+// target=native