diff --git a/doc/langref/grammar.peg b/doc/langref/grammar.peg index efbe0ca0013fdcc348c0fb7ef1b74d8301a6b33a..3b88469e4d90cc2ada0bc96e348d3b03a59d80e9 100644 --- a/doc/langref/grammar.peg +++ b/doc/langref/grammar.peg @@ -126,7 +126,7 @@ BoolOrExpr <- BoolAndExpr (OrOp BoolAndExpr)* !OrOp BoolAndExpr <- CompareExpr (AndOp CompareExpr)* !AndOp -CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr / !CompareOp) +CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? !CompareOp BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* !BitwiseOp diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index f182436dbb4296e05bdc8c2e272f127ce946cbd1..b2ae33b8029edd2ed0802e01725da43193a0648c 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -140,6 +140,11 @@ test "bin op at end of file" { ); } +// Found using AFL++ +test "resume block chained compare ops" { + try checkAgainstOracle("test{resume{0 > 0;} > 0 > 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 78a24973c9c3de5e4ae5ce577a2ca6db558bfddb..65022c39394a3ec715d7cacc5673f10070f49767 100644 --- a/lib/std/zig/parser_generated_oracle.zig +++ b/lib/std/zig/parser_generated_oracle.zig @@ -639,18 +639,16 @@ const Parser = struct { pub fn parseCompareExpr(p: *Parser) Error!bool { return blk_0: { const pos_0 = p.i; - if (try p.parseBitwiseExpr() and blk_2: { - const pos_2 = p.i; - if (try p.parseCompareOp() and try p.parseBitwiseExpr()) break :blk_2 true; - p.i = pos_2; - if (blk_3: { - const pos_3 = p.i; - const match_3 = try p.parseCompareOp(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - break :blk_2 false; + if (try p.parseBitwiseExpr() and (blk_3: { + const pos_3 = p.i; + if (try p.parseCompareOp() and try p.parseBitwiseExpr()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + } or true) and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseCompareOp(); + p.i = pos_1; + break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; break :blk_0 false;