Commit ab22844176

Andrew Kelley <andrew@ziglang.org>
2024-03-21 00:29:30
frontend: add missing bounds check for slice-by-length arrays
closes #18382
1 parent 5005c62
Changed files (2)
src/Sema.zig
@@ -33284,12 +33284,16 @@ fn analyzeSlice(
                     try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null);
                 }
 
-                if (slice_ty.isSlice(mod)) {
-                    const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
-                    const actual_len = if (slice_ty.sentinel(mod) == null)
-                        slice_len_inst
-                    else
-                        try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
+                bounds_check: {
+                    const actual_len = if (array_ty.zigTypeTag(mod) == .Array)
+                        try mod.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(mod))
+                    else if (slice_ty.isSlice(mod)) l: {
+                        const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
+                        break :l if (slice_ty.sentinel(mod) == null)
+                            slice_len_inst
+                        else
+                            try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
+                    } else break :bounds_check;
 
                     const actual_end = if (slice_sentinel != null)
                         try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
test/cases/safety/out of bounds array slice by length.zig
@@ -0,0 +1,20 @@
+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 16, len 5")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    var buf: [5]u8 = undefined;
+    _ = buf[foo(6)..][0..10];
+    return error.TestFailed;
+}
+fn foo(a: u32) u32 {
+    return a;
+}
+// run
+// backend=llvm
+// target=native