authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-03-01 21:07:07+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-01 16:09:57-08:00
log7b5b7bda87dc4121e2942042d19fd375c73f90e5
treed4e28868de6b2d6de9b81914773020c65ad55a71
parentcd7c870bd81391dd97c5c75eb3910382ba7280a1

parser: fix infinite loop on missing comma in param list


2 files changed, 24 insertions(+), 20 deletions(-)

lib/std/zig/parse.zig+12-20
...@@ -3714,7 +3714,6 @@ const Parser = struct {...@@ -3714,7 +3714,6 @@ const Parser = struct {
3714 if (p.eatToken(.r_paren)) |_| {3714 if (p.eatToken(.r_paren)) |_| {
3715 return SmallSpan{ .zero_or_one = 0 };3715 return SmallSpan{ .zero_or_one = 0 };
3716 }3716 }
3717 continue;
3718 },3717 },
3719 .r_paren => return SmallSpan{ .zero_or_one = 0 },3718 .r_paren => return SmallSpan{ .zero_or_one = 0 },
3720 else => {3719 else => {
...@@ -3728,14 +3727,7 @@ const Parser = struct {...@@ -3728,14 +3727,7 @@ const Parser = struct {
37283727
3729 const param_two = while (true) {3728 const param_two = while (true) {
3730 switch (p.token_tags[p.nextToken()]) {3729 switch (p.token_tags[p.nextToken()]) {
3731 .comma => {3730 .comma => {},
3732 if (p.eatToken(.r_paren)) |_| {
3733 return SmallSpan{ .zero_or_one = param_one };
3734 }
3735 const param = try p.expectParamDecl();
3736 if (param != 0) break param;
3737 continue;
3738 },
3739 .r_paren => return SmallSpan{ .zero_or_one = param_one },3731 .r_paren => return SmallSpan{ .zero_or_one = param_one },
3740 .colon, .r_brace, .r_bracket => {3732 .colon, .r_brace, .r_bracket => {
3741 p.tok_i -= 1;3733 p.tok_i -= 1;
...@@ -3748,6 +3740,11 @@ const Parser = struct {...@@ -3748,6 +3740,11 @@ const Parser = struct {
3748 try p.warnExpected(.comma);3740 try p.warnExpected(.comma);
3749 },3741 },
3750 }3742 }
3743 if (p.eatToken(.r_paren)) |_| {
3744 return SmallSpan{ .zero_or_one = param_one };
3745 }
3746 const param = try p.expectParamDecl();
3747 if (param != 0) break param;
3751 } else unreachable;3748 } else unreachable;
37523749
3753 var list = std.ArrayList(Node.Index).init(p.gpa);3750 var list = std.ArrayList(Node.Index).init(p.gpa);
...@@ -3757,17 +3754,7 @@ const Parser = struct {...@@ -3757,17 +3754,7 @@ const Parser = struct {
37573754
3758 while (true) {3755 while (true) {
3759 switch (p.token_tags[p.nextToken()]) {3756 switch (p.token_tags[p.nextToken()]) {
3760 .comma => {3757 .comma => {},
3761 if (p.token_tags[p.tok_i] == .r_paren) {
3762 p.tok_i += 1;
3763 return SmallSpan{ .multi = list.toOwnedSlice() };
3764 }
3765 const param = try p.expectParamDecl();
3766 if (param != 0) {
3767 try list.append(param);
3768 }
3769 continue;
3770 },
3771 .r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },3758 .r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },
3772 .colon, .r_brace, .r_bracket => {3759 .colon, .r_brace, .r_bracket => {
3773 p.tok_i -= 1;3760 p.tok_i -= 1;
...@@ -3780,6 +3767,11 @@ const Parser = struct {...@@ -3780,6 +3767,11 @@ const Parser = struct {
3780 try p.warnExpected(.comma);3767 try p.warnExpected(.comma);
3781 },3768 },
3782 }3769 }
3770 if (p.eatToken(.r_paren)) |_| {
3771 return SmallSpan{ .multi = list.toOwnedSlice() };
3772 }
3773 const param = try p.expectParamDecl();
3774 if (param != 0) try list.append(param);
3783 }3775 }
3784 }3776 }
37853777
lib/std/zig/parser_test.zig+12
...@@ -4549,6 +4549,18 @@ test "recovery: missing for payload" {...@@ -4549,6 +4549,18 @@ test "recovery: missing for payload" {
4549 });4549 });
4550}4550}
45514551
4552test "recovery: missing comma in params" {
4553 try testError(
4554 \\fn foo(comptime bool what what) void { }
4555 \\fn bar(a: i32, b: i32 c) void { }
4556 \\
4557 , &[_]Error{
4558 .expected_token,
4559 .expected_token,
4560 .expected_token,
4561 });
4562}
4563
4552const std = @import("std");4564const std = @import("std");
4553const mem = std.mem;4565const mem = std.mem;
4554const warn = std.debug.warn;4566const warn = std.debug.warn;