diff --git a/doc/langref/grammar.peg b/doc/langref/grammar.peg index 46e6859b6fa40ae3e63bc849fabe55d4cd97e02a..83f75509cac2d5649a47ab3a506c4a24919b68b5 100644 --- a/doc/langref/grammar.peg +++ b/doc/langref/grammar.peg @@ -272,7 +272,7 @@ CompareOpTok BitwiseOp <- pre_op_white BitwiseOpTok post_op_white / !pre_op_white BitwiseOpTok !post_op_white BitwiseOpTok - <- AMPERSAND + <- AMPERSAND ![&] / CARET / PIPE / KEYWORD_orelse diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index 6086ed4d319c323c47718ea9a504c6419dae5499..c226dfe58dda7375d4407951161466ec7e8419ab 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -30,6 +30,12 @@ test "doc comment or division operator" { try checkAgainstOracle("0=0///\n0"); } +// Found using AFL++ +test "double ampersand" { + try checkAgainstOracle("0=0&&0"); // error + try checkAgainstOracle("test{&&0;}"); // ok +} + 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 69f23ec3139b3a0da3ff06a82c2b1d910fcf47b4..7be3e2e4a15d99b287f33d1553f10e1ec5fff176 100644 --- a/lib/std/zig/parser_generated_oracle.zig +++ b/lib/std/zig/parser_generated_oracle.zig @@ -1528,7 +1528,19 @@ const Parser = struct { pub fn parseBitwiseOpTok(p: *Parser) bool { return blk_0: { const pos_0 = p.i; - if (p.parseAMPERSAND()) break :blk_0 true; + if (p.parseAMPERSAND() and blk_1: { + const pos_1 = p.i; + const match_1 = (p.i < p.source.len and switch (p.source[p.i]) { + '&'...'&', + => blk_2: { + p.i += 1; + break :blk_2 true; + }, + else => false, + }); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; p.i = pos_0; if (p.parseCARET()) break :blk_0 true; p.i = pos_0;