diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 372823324ee4205c31b15cf145d4c2b9b055fe42..260f62abbb0871a1332978640b1b675a9c2156e9 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -559,12 +559,6 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void .var_const_decl => { return w.writeAll("use 'var' or 'const' to declare variable"); }, - .extra_for_capture => { - return w.writeAll("extra capture in for loop"); - }, - .for_input_not_captured => { - return w.writeAll("for input is not captured"); - }, .invalid_byte => { const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..]; @@ -2889,8 +2883,6 @@ pub const Error = struct { expected_var_const, wrong_equal_var_decl, var_const_decl, - extra_for_capture, - for_input_not_captured, zig_style_container, previous_field, diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 4adf7d0232804afe4738add9bf7a5307e2f1cdd3..e41536f7d456fb0ccf8397742558971d0e5ce7d4 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -6708,6 +6708,9 @@ fn forExpr( for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| { const capture_is_ref = tree.tokenTag(capture_token) == .asterisk; const ident_tok = capture_token + @intFromBool(capture_is_ref); + if (tree.tokenTag(ident_tok) != .identifier) { + return astgen.failNode(input, "for input is not captured", .{}); + } const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_"); if (is_discard and capture_is_ref) { @@ -6750,6 +6753,10 @@ fn forExpr( len_refs.* = .{ indexable, .none }; } } + // There may or may not be a trailing comma after the final capture + if (tree.tokenTag(capture_token) != .pipe and tree.tokenTag(capture_token - 1) != .pipe) { + return astgen.failTok(capture_token, "extra capture in for loop", .{}); + } } if (!any_len_checks) { diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index d4c6015131d4c612633e3b87f8da61f0faeaf6a4..0978bad73823deb2a0a47dc68a1064cd9923e352 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -2106,16 +2106,9 @@ fn forPrefix(p: *Parse) Error!usize { return inputs; }; - var warned_excess = false; - var captures: u32 = 0; while (true) { _ = p.eatToken(.asterisk); - const identifier = try p.expectToken(.identifier); - captures += 1; - if (captures > inputs and !warned_excess) { - try p.warnMsg(.{ .tag = .extra_for_capture, .token = identifier }); - warned_excess = true; - } + _ = try p.expectToken(.identifier); switch (p.tokenTag(p.tok_i)) { .comma => p.tok_i += 1, .pipe => { @@ -2128,11 +2121,6 @@ fn forPrefix(p: *Parse) Error!usize { if (p.eatToken(.pipe)) |_| break; } - if (captures < inputs) { - const index = p.scratch.items.len - captures; - const input = p.nodeMainToken(p.scratch.items[index]); - try p.warnMsg(.{ .tag = .for_input_not_captured, .token = input }); - } return inputs; } diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index dcf20ccb69d3337a8a39b6dc946872d784850c9c..62e6d18e264842c474870bd6a8d60bf5992193cf 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -52,6 +52,11 @@ test "newline required before doc comment not at start of file" { try checkAgainstOracle("///\ntest {}"); } +// Found using AFL++ +test "extra capture in for loop" { + try checkAgainstOracle("for(0)|t,r|0"); +} + fn checkAgainstOracle(source: [:0]const u8) !void { var fba_buf: [1 << 18]u8 = undefined; var fba: std.heap.FixedBufferAllocator = .init(&fba_buf);