Commit 7b5b7bda87

Isaac Freund <ifreund@ifreund.xyz>
2021-03-01 21:07:07
parser: fix infinite loop on missing comma in param list
1 parent cd7c870
Changed files (2)
lib/std/zig/parse.zig
@@ -3714,7 +3714,6 @@ const Parser = struct {
                     if (p.eatToken(.r_paren)) |_| {
                         return SmallSpan{ .zero_or_one = 0 };
                     }
-                    continue;
                 },
                 .r_paren => return SmallSpan{ .zero_or_one = 0 },
                 else => {
@@ -3728,14 +3727,7 @@ const Parser = struct {
 
         const param_two = while (true) {
             switch (p.token_tags[p.nextToken()]) {
-                .comma => {
-                    if (p.eatToken(.r_paren)) |_| {
-                        return SmallSpan{ .zero_or_one = param_one };
-                    }
-                    const param = try p.expectParamDecl();
-                    if (param != 0) break param;
-                    continue;
-                },
+                .comma => {},
                 .r_paren => return SmallSpan{ .zero_or_one = param_one },
                 .colon, .r_brace, .r_bracket => {
                     p.tok_i -= 1;
@@ -3748,6 +3740,11 @@ const Parser = struct {
                     try p.warnExpected(.comma);
                 },
             }
+            if (p.eatToken(.r_paren)) |_| {
+                return SmallSpan{ .zero_or_one = param_one };
+            }
+            const param = try p.expectParamDecl();
+            if (param != 0) break param;
         } else unreachable;
 
         var list = std.ArrayList(Node.Index).init(p.gpa);
@@ -3757,17 +3754,7 @@ const Parser = struct {
 
         while (true) {
             switch (p.token_tags[p.nextToken()]) {
-                .comma => {
-                    if (p.token_tags[p.tok_i] == .r_paren) {
-                        p.tok_i += 1;
-                        return SmallSpan{ .multi = list.toOwnedSlice() };
-                    }
-                    const param = try p.expectParamDecl();
-                    if (param != 0) {
-                        try list.append(param);
-                    }
-                    continue;
-                },
+                .comma => {},
                 .r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },
                 .colon, .r_brace, .r_bracket => {
                     p.tok_i -= 1;
@@ -3780,6 +3767,11 @@ const Parser = struct {
                     try p.warnExpected(.comma);
                 },
             }
+            if (p.eatToken(.r_paren)) |_| {
+                return SmallSpan{ .multi = list.toOwnedSlice() };
+            }
+            const param = try p.expectParamDecl();
+            if (param != 0) try list.append(param);
         }
     }
 
lib/std/zig/parser_test.zig
@@ -4549,6 +4549,18 @@ test "recovery: missing for payload" {
     });
 }
 
+test "recovery: missing comma in params" {
+    try testError(
+        \\fn foo(comptime bool what what) void { }
+        \\fn bar(a: i32, b: i32 c) void { }
+        \\
+    , &[_]Error{
+        .expected_token,
+        .expected_token,
+        .expected_token,
+    });
+}
+
 const std = @import("std");
 const mem = std.mem;
 const warn = std.debug.warn;