Skip to content

Commit 6aa438f

Browse files
committed
Sema: add null pointer slice safety check when len is comptime known
1 parent eec2978 commit 6aa438f

7 files changed

+42
-15
lines changed

src/Sema.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25569,6 +25569,11 @@ fn analyzeSlice(
2556925569
const new_ptr_val = opt_new_ptr_val orelse {
2557025570
const result = try block.addBitCast(return_ty, new_ptr);
2557125571
if (block.wantSafety()) {
25572+
// requirement: slicing C ptr is non-null
25573+
if (ptr_ptr_child_ty.isCPtr()) {
25574+
const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
25575+
try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
25576+
}
2557225577
// requirement: result[new_len] == slice_sentinel
2557325578
try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
2557425579
}

test/cases/safety/pointer slice sentinel mismatch.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ const std = @import("std");
22

33
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
44
_ = stack_trace;
5-
if (std.mem.eql(u8, message, "sentinel mismatch")) {
5+
if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) {
66
std.process.exit(0);
77
}
88
std.process.exit(1);
99
}
1010

1111
pub fn main() !void {
12-
var buf: [4]u8 = undefined;
12+
var buf: [4]u8 = .{ 1, 2, 3, 4 };
1313
const ptr: [*]u8 = &buf;
1414
const slice = ptr[0..3 :0];
1515
_ = slice;
1616
return error.TestFailed;
1717
}
1818

1919
// run
20-
// backend=stage1
20+
// backend=llvm
2121
// target=native

test/cases/safety/slice sentinel mismatch - floats.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ const std = @import("std");
22

33
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
44
_ = stack_trace;
5-
if (std.mem.eql(u8, message, "sentinel mismatch")) {
5+
if (std.mem.eql(u8, message, "sentinel mismatch: expected 1.20000004e+00, found 4.0e+00")) {
66
std.process.exit(0);
77
}
88
std.process.exit(1);
99
}
1010

1111
pub fn main() !void {
12-
var buf: [4]f32 = undefined;
12+
var buf: [4]f32 = .{ 1, 2, 3, 4 };
1313
const slice = buf[0..3 :1.2];
1414
_ = slice;
1515
return error.TestFailed;
1616
}
1717

1818
// run
19-
// backend=stage1
19+
// backend=llvm
2020
// target=native

test/cases/safety/slice sentinel mismatch - optional pointers.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ const std = @import("std");
22

33
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
44
_ = stack_trace;
5-
if (std.mem.eql(u8, message, "sentinel mismatch")) {
5+
if (std.mem.eql(u8, message, "sentinel mismatch: expected null, found i32@10")) {
66
std.process.exit(0);
77
}
88
std.process.exit(1);
99
}
1010

1111
pub fn main() !void {
12-
var buf: [4]?*i32 = undefined;
12+
var buf: [4]?*i32 = .{ @intToPtr(*i32, 4), @intToPtr(*i32, 8), @intToPtr(*i32, 12), @intToPtr(*i32, 16) };
1313
const slice = buf[0..3 :null];
1414
_ = slice;
1515
return error.TestFailed;
1616
}
1717

1818
// run
19-
// backend=stage1
19+
// backend=llvm
2020
// target=native

test/cases/safety/slice slice sentinel mismatch.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ const std = @import("std");
22

33
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
44
_ = stack_trace;
5-
if (std.mem.eql(u8, message, "sentinel mismatch")) {
5+
if (std.mem.eql(u8, message, "sentinel mismatch: expected 0, found 4")) {
66
std.process.exit(0);
77
}
88
std.process.exit(1);
99
}
1010
pub fn main() !void {
11-
var buf: [4]u8 = undefined;
11+
var buf: [4]u8 = .{ 1, 2, 3, 4 };
1212
const slice = buf[0..];
1313
const slice2 = slice[0..3 :0];
1414
_ = slice2;
1515
return error.TestFailed;
1616
}
1717
// run
18-
// backend=stage1
18+
// backend=llvm
1919
// target=native
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const std = @import("std");
2+
3+
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4+
_ = stack_trace;
5+
if (std.mem.eql(u8, message, "attempt to use null value")) {
6+
std.process.exit(0);
7+
}
8+
std.process.exit(1);
9+
}
10+
11+
pub fn main() !void {
12+
var ptr: [*c]const u32 = null;
13+
var len: usize = 3;
14+
var slice = ptr[0..len];
15+
_ = slice;
16+
return error.TestFailed;
17+
}
18+
// run
19+
// backend=llvm
20+
// target=native
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const std = @import("std");
22

33
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
4-
_ = message;
54
_ = stack_trace;
6-
std.process.exit(0);
5+
if (std.mem.eql(u8, message, "attempt to use null value")) {
6+
std.process.exit(0);
7+
}
8+
std.process.exit(1);
79
}
810

911
pub fn main() !void {
@@ -13,5 +15,5 @@ pub fn main() !void {
1315
return error.TestFailed;
1416
}
1517
// run
16-
// backend=stage1
18+
// backend=llvm
1719
// target=native

0 commit comments

Comments
 (0)