From 581d292381157464ae6f2c88c8a628314f005742 Mon Sep 17 00:00:00 2001 From: travisstaloch Date: Fri, 23 Dec 2022 13:10:04 -0800 Subject: [PATCH] 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. --- lib/std/zig/Ast.zig | 2 +- test/behavior.zig | 1 + test/behavior/empty_file_level_struct.zig | 1 + test/behavior/empty_file_level_union.zig | 1 + test/behavior/empty_tuple_fields.zig | 26 +++++++++++++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/behavior/empty_file_level_struct.zig create mode 100644 test/behavior/empty_file_level_union.zig create mode 100644 test/behavior/empty_tuple_fields.zig diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index c2439437e79914885c19917b119be51367c97a90..74b104847091ac40e71d8f502706b9ac91d7268b 100644 --- a/lib/std/zig/Ast.zig +++ b/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 => {}, } diff --git a/test/behavior.zig b/test/behavior.zig index 4a70cb010b509311217314c02a0ce20d3786bf9f..36403a8f0cad5bead0358b2c3253dc0a7b3648f9 100644 --- a/test/behavior.zig +++ b/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"); diff --git a/test/behavior/empty_file_level_struct.zig b/test/behavior/empty_file_level_struct.zig new file mode 100644 index 0000000000000000000000000000000000000000..86f0f2b3c7f579279b17bab584b232f8002398bf --- /dev/null +++ b/test/behavior/empty_file_level_struct.zig @@ -0,0 +1 @@ +struct {} diff --git a/test/behavior/empty_file_level_union.zig b/test/behavior/empty_file_level_union.zig new file mode 100644 index 0000000000000000000000000000000000000000..0d24797ffb6565c4012b5aff0ab04a9860602959 --- /dev/null +++ b/test/behavior/empty_file_level_union.zig @@ -0,0 +1 @@ +union {} diff --git a/test/behavior/empty_tuple_fields.zig b/test/behavior/empty_tuple_fields.zig new file mode 100644 index 0000000000000000000000000000000000000000..7309dc9b3e9b3b3feb8aa0718d94dab3a3f0b4a3 --- /dev/null +++ b/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); +} -- 2.54.0