From 4fa5b59d4470daa595b67e36ceb8290064cbc8a7 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 3 Jul 2026 14:12:25 +0200 Subject: [PATCH] grammar: fix catch operator whitespace handling This now matches the behavior of Parse.zig --- doc/langref/grammar.peg | 3 ++- lib/std/zig/parser_fuzz.zig | 5 +++++ lib/std/zig/parser_generated_oracle.zig | 16 ++++++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/langref/grammar.peg b/doc/langref/grammar.peg index d52e432ef70c5ef810fdd592f9817c24134b7332..ccb86d02fa4ee5983062dd0ce735a752694459d8 100644 --- a/doc/langref/grammar.peg +++ b/doc/langref/grammar.peg @@ -318,12 +318,13 @@ CompareOpTok BitwiseOp <- pre_op_white BitwiseOpTok post_op_white / !pre_op_white BitwiseOpTok !post_op_white + / pre_op_white KEYWORD_catch post_op_white Payload? + / !pre_op_white KEYWORD_catch !post_op_white Payload? BitwiseOpTok <- AMPERSAND ![&] / CARET / PIPE / KEYWORD_orelse - / KEYWORD_catch Payload? BitShiftOp <- pre_op_white BitShiftOpTok post_op_white / !pre_op_white BitShiftOpTok !post_op_white diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index f68e20da34674fe894992786d1b400112205175f..cb17a588bbbc4891863301412e978bfd8d937fca 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -114,6 +114,11 @@ test "volatile const" { try checkAgainstOracle("*volatile\nconst\n0"); } +// Found using AFL++ +test "catch capture whitespace" { + try checkAgainstOracle("test{0 catch |h|0;}"); +} + fn checkAgainstOracle(source: [:0]const u8) !void { var fba_buf: [1 << 18]u8 = undefined; var fba: std.heap.FixedBufferAllocator = .init(&fba_buf); diff --git a/lib/std/zig/parser_generated_oracle.zig b/lib/std/zig/parser_generated_oracle.zig index da7f0d9539abc02b2d32ecd185e575c0730a784a..e20f0c2b347ce36be29d4b8957809d503eaf17ab 100644 --- a/lib/std/zig/parser_generated_oracle.zig +++ b/lib/std/zig/parser_generated_oracle.zig @@ -1665,6 +1665,20 @@ const Parser = struct { break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; + if (try p.parsepre_op_white() and try p.parseKEYWORD_catch() and try p.parsepost_op_white() and (try p.parsePayload() or true)) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseKEYWORD_catch() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and (try p.parsePayload() or true)) break :blk_0 true; + p.i = pos_0; break :blk_0 false; }; } @@ -1691,8 +1705,6 @@ const Parser = struct { p.i = pos_0; if (try p.parseKEYWORD_orelse()) break :blk_0 true; p.i = pos_0; - if (try p.parseKEYWORD_catch() and (try p.parsePayload() or true)) break :blk_0 true; - p.i = pos_0; break :blk_0 false; }; } -- 2.54.0