Commit 581d292381

travisstaloch <twostepted@gmail.com>
2022-12-23 22:10:04
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.
1 parent bb62d51
lib/std/zig/Ast.zig
@@ -618,7 +618,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
         .tagged_union_enum_tag_trailing,
         => {
             const main_token = main_tokens[n];
-            switch (token_tags[main_token - 1]) {
+            switch (token_tags[main_token -| 1]) {
                 .keyword_packed, .keyword_extern => end_offset += 1,
                 else => {},
             }
test/behavior/empty_file_level_struct.zig
@@ -0,0 +1,1 @@
+struct {}
test/behavior/empty_file_level_union.zig
@@ -0,0 +1,1 @@
+union {}
test/behavior/empty_tuple_fields.zig
@@ -0,0 +1,26 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+test "empty file level struct" {
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const T = @import("empty_file_level_struct.zig");
+    const info = @typeInfo(T);
+    try std.testing.expectEqual(@as(usize, 1), info.Struct.fields.len);
+    try std.testing.expectEqualStrings("0", info.Struct.fields[0].name);
+    try std.testing.expect(@typeInfo(info.Struct.fields[0].type) == .Struct);
+}
+
+test "empty file level union" {
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const T = @import("empty_file_level_union.zig");
+    const info = @typeInfo(T);
+    try std.testing.expectEqual(@as(usize, 1), info.Struct.fields.len);
+    try std.testing.expectEqualStrings("0", info.Struct.fields[0].name);
+    try std.testing.expect(@typeInfo(info.Struct.fields[0].type) == .Union);
+}
test/behavior.zig
@@ -151,6 +151,7 @@ test {
     _ = @import("behavior/const_slice_child.zig");
     _ = @import("behavior/decltest.zig");
     _ = @import("behavior/defer.zig");
+    _ = @import("behavior/empty_tuple_fields.zig");
     _ = @import("behavior/empty_union.zig");
     _ = @import("behavior/enum.zig");
     _ = @import("behavior/error.zig");