authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2024-12-29 06:47:15+01:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2024-12-29 07:00:39+01:00
log5b6326ec6540d1b7af8de1176f657672be72a1e4
tree60d3a3c3ad1f5c68d12c33ae7b4181af9331fc1c
parent5d51d4474a0c61f08c264c03ecbdf651d91afe82
signaturebadge-check Signed by SSH key SHA256:HYC3SjXQcAt6uwv9pu/6OoVQ2rUH8rb5zKiUHSe9uxk

fix slice of slice with sentinel on the lhs slice

example: ```zig test { var foo: [2:0]u8 = .{ 1, 2 }; _ = foo[0.. :1][0..2]; } ``` A `.slice_open` ast node will not have a end index nor sentinel.

4 files changed, 57 insertions(+), 11 deletions(-)

lib/std/zig/AstGen.zig+4-11
...@@ -881,21 +881,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -881,21 +881,14 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
881 .slice_sentinel,881 .slice_sentinel,
882 => {882 => {
883 const full = tree.fullSlice(node).?;883 const full = tree.fullSlice(node).?;
884 const lhs_tag = node_tags[full.ast.sliced];
885 const lhs_is_slice_sentinel = lhs_tag == .slice_sentinel;
886 const lhs_is_open_slice = lhs_tag == .slice_open or
887 (lhs_is_slice_sentinel and tree.fullSlice(full.ast.sliced).?.ast.end == 0);
888 if (full.ast.end != 0 and884 if (full.ast.end != 0 and
889 lhs_is_open_slice and885 node_tags[full.ast.sliced] == .slice_open and
890 nodeIsTriviallyZero(tree, full.ast.start))886 nodeIsTriviallyZero(tree, full.ast.start))
891 {887 {
892 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[full.ast.sliced].lhs);888 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
893
894 const start = if (lhs_is_slice_sentinel) start: {
895 const lhs_extra = tree.extraData(node_datas[full.ast.sliced].rhs, Ast.Node.SliceSentinel);
896 break :start try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);
897 } else try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[full.ast.sliced].rhs);
898889
890 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);
891 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);
899 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);892 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
900 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);893 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);
901 const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none;894 const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none;
test/behavior/slice.zig+17
...@@ -115,6 +115,23 @@ test "open slice of open slice with sentinel" {...@@ -115,6 +115,23 @@ test "open slice of open slice with sentinel" {
115 try expect(slice[1..][0.. :0][4] == 0);115 try expect(slice[1..][0.. :0][4] == 0);
116}116}
117117
118test "open slice with sentinel of slice with end index" {
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120
121 var slice: [:0]const u8 = "hello";
122 _ = &slice;
123
124 comptime assert(@TypeOf(slice[0.. :0][0..5]) == *const [5]u8);
125 try expect(slice[0.. :0][0..5].len == 5);
126 try expect(slice[0.. :0][0..5][0] == 'h');
127 try expect(slice[0.. :0][0..5][4] == 'o');
128
129 comptime assert(@TypeOf(slice[0.. :0][0..5 :0]) == *const [5:0]u8);
130 try expect(slice[0.. :0][0..5 :0].len == 5);
131 try expect(slice[0.. :0][0..5 :0][0] == 'h');
132 try expect(slice[0.. :0][0..5 :0][5] == 0);
133}
134
118test "slice of type" {135test "slice of type" {
119 comptime {136 comptime {
120 var types_array = [_]type{ i32, f64, type };137 var types_array = [_]type{ i32, f64, type };
test/cases/safety/slice by length sentinel mismatch on lhs.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "sentinel mismatch: expected 1, found 3")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buf: [4:0]u8 = .{ 1, 2, 3, 4 };
12 const slice = buf[0..][0..2 :1];
13 _ = slice;
14 return error.TestFailed;
15}
16// run
17// backend=llvm
18// target=native
test/cases/safety/slice by length sentinel mismatch on rhs.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "sentinel mismatch: expected 1, found 0")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buf: [4:0]u8 = .{ 1, 2, 3, 4 };
12 const slice = buf[0.. :1][0..2];
13 _ = slice;
14 return error.TestFailed;
15}
16// run
17// backend=llvm
18// target=native