authorgravatar for twostepted@gmail.comTravis Staloch <twostepted@gmail.com> 2022-12-23 13:10:04-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-23 23:10:04+02:00
log581d292381157464ae6f2c88c8a628314f005742
tree1d67f07416fb6d45e54267e459ebda5c7581e1d0
parentbb62d5105ca02a8b1c959ccf79b9f2861505a150
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

fix overflow found while fuzzing

* allow file level `union {}` to parse as tuple field this was found while fuzzing zls. * before this patch the input `union {}` crashed the parser. after this, it parses correctly just like `struct {}`. * adds behavior tests for both inputs `struct {}` and `union {}`, checking that each becomes a file level tuple field.

5 files changed, 30 insertions(+), 1 deletions(-)

lib/std/zig/Ast.zig+1-1
......@@ -618,7 +618,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
618618 .tagged_union_enum_tag_trailing,
619619 => {
620620 const main_token = main_tokens[n];
621 switch (token_tags[main_token - 1]) {
621 switch (token_tags[main_token -| 1]) {
622622 .keyword_packed, .keyword_extern => end_offset += 1,
623623 else => {},
624624 }
test/behavior.zig+1
......@@ -151,6 +151,7 @@ test {
151151 _ = @import("behavior/const_slice_child.zig");
152152 _ = @import("behavior/decltest.zig");
153153 _ = @import("behavior/defer.zig");
154 _ = @import("behavior/empty_tuple_fields.zig");
154155 _ = @import("behavior/empty_union.zig");
155156 _ = @import("behavior/enum.zig");
156157 _ = @import("behavior/error.zig");
test/behavior/empty_file_level_struct.zig created+1
......@@ -0,0 +1 @@
1struct {}
test/behavior/empty_file_level_union.zig created+1
......@@ -0,0 +1 @@
1union {}
test/behavior/empty_tuple_fields.zig created+26
......@@ -0,0 +1,26 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4test "empty file level struct" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8
9 const T = @import("empty_file_level_struct.zig");
10 const info = @typeInfo(T);
11 try std.testing.expectEqual(@as(usize, 1), info.Struct.fields.len);
12 try std.testing.expectEqualStrings("0", info.Struct.fields[0].name);
13 try std.testing.expect(@typeInfo(info.Struct.fields[0].type) == .Struct);
14}
15
16test "empty file level union" {
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20
21 const T = @import("empty_file_level_union.zig");
22 const info = @typeInfo(T);
23 try std.testing.expectEqual(@as(usize, 1), info.Struct.fields.len);
24 try std.testing.expectEqualStrings("0", info.Struct.fields[0].name);
25 try std.testing.expect(@typeInfo(info.Struct.fields[0].type) == .Union);
26}