Commit 6aa438f065

Veikka Tuominen <git@vexu.eu>
2022-08-05 15:50:27
Sema: add null pointer slice safety check when len is comptime known
1 parent eec2978
src/Sema.zig
@@ -25569,6 +25569,11 @@ fn analyzeSlice(
         const new_ptr_val = opt_new_ptr_val orelse {
             const result = try block.addBitCast(return_ty, new_ptr);
             if (block.wantSafety()) {
+                // requirement: slicing C ptr is non-null
+                if (ptr_ptr_child_ty.isCPtr()) {
+                    const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
+                    try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
+                }
                 // requirement: result[new_len] == slice_sentinel
                 try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
             }
test/cases/safety/pointer slice sentinel mismatch.zig
@@ -2,14 +2,14 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+    if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) {
         std.process.exit(0);
     }
     std.process.exit(1);
 }
 
 pub fn main() !void {
-    var buf: [4]u8 = undefined;
+    var buf: [4]u8 = .{ 1, 2, 3, 4 };
     const ptr: [*]u8 = &buf;
     const slice = ptr[0..3 :0];
     _ = slice;
@@ -17,5 +17,5 @@ pub fn main() !void {
 }
 
 // run
-// backend=stage1
+// backend=llvm
 // target=native
test/cases/safety/slice sentinel mismatch - floats.zig
@@ -2,19 +2,19 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+    if (std.mem.eql(u8, message, "sentinel mismatch: expected 1.20000004e+00, found 4.0e+00")) {
         std.process.exit(0);
     }
     std.process.exit(1);
 }
 
 pub fn main() !void {
-    var buf: [4]f32 = undefined;
+    var buf: [4]f32 = .{ 1, 2, 3, 4 };
     const slice = buf[0..3 :1.2];
     _ = slice;
     return error.TestFailed;
 }
 
 // run
-// backend=stage1
+// backend=llvm
 // target=native
test/cases/safety/slice sentinel mismatch - optional pointers.zig
@@ -2,19 +2,19 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+    if (std.mem.eql(u8, message, "sentinel mismatch: expected null, found i32@10")) {
         std.process.exit(0);
     }
     std.process.exit(1);
 }
 
 pub fn main() !void {
-    var buf: [4]?*i32 = undefined;
+    var buf: [4]?*i32 = .{ @intToPtr(*i32, 4), @intToPtr(*i32, 8), @intToPtr(*i32, 12), @intToPtr(*i32, 16) };
     const slice = buf[0..3 :null];
     _ = slice;
     return error.TestFailed;
 }
 
 // run
-// backend=stage1
+// backend=llvm
 // target=native
test/cases/safety/slice slice sentinel mismatch.zig
@@ -2,18 +2,18 @@ const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
     _ = stack_trace;
-    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+    if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) {
         std.process.exit(0);
     }
     std.process.exit(1);
 }
 pub fn main() !void {
-    var buf: [4]u8 = undefined;
+    var buf: [4]u8 = .{ 1, 2, 3, 4 };
     const slice = buf[0..];
     const slice2 = slice[0..3 :0];
     _ = slice2;
     return error.TestFailed;
 }
 // run
-// backend=stage1
+// backend=llvm
 // target=native
test/cases/safety/slicing null C pointer runtime len.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to use null value")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var ptr: [*c]const u32 = null;
+    var len: usize = 3;
+    var slice = ptr[0..len];
+    _ = slice;
+    return error.TestFailed;
+}
+// run
+// backend=llvm
+// target=native
\ No newline at end of file
test/cases/safety/slicing null C pointer.zig
@@ -1,9 +1,11 @@
 const std = @import("std");
 
 pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-    _ = message;
     _ = stack_trace;
-    std.process.exit(0);
+    if (std.mem.eql(u8, message, "attempt to use null value")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
 }
 
 pub fn main() !void {
@@ -13,5 +15,5 @@ pub fn main() !void {
     return error.TestFailed;
 }
 // run
-// backend=stage1
+// backend=llvm
 // target=native
\ No newline at end of file