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.
This commit is contained in:
travisstaloch 2022-12-23 13:10:04 -08:00 committed by GitHub
parent bb62d5105c
commit 581d292381
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 1 deletions

View File

@ -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 => {},
}

View File

@ -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");

View File

@ -0,0 +1 @@
struct {}

View File

@ -0,0 +1 @@
union {}

View File

@ -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);
}