| author | |
| committer | |
| log | e539f7bbebc8016ea05b9203c8be371db8b2e90d |
| tree | d98fcc99e470cd871d8f7b66ee4c44a475080b26 |
| parent | 153fcc4e9c7dfea91472a9456d95ff5abb3b8649 |
| signature |
This matches the Parse.zig implementation, which has a special parse
error for this case:
> ambiguous use of '&&'; use 'and' for logical AND, or change whitespace
> to ' & &' for bitwise AND3 files changed, 20 insertions(+), 2 deletions(-)
doc/langref/grammar.peg+1-1| ... | @@ -272,7 +272,7 @@ CompareOpTok | ... | @@ -272,7 +272,7 @@ CompareOpTok |
| 272 | BitwiseOp <- pre_op_white BitwiseOpTok post_op_white | 272 | BitwiseOp <- pre_op_white BitwiseOpTok post_op_white |
| 273 | / !pre_op_white BitwiseOpTok !post_op_white | 273 | / !pre_op_white BitwiseOpTok !post_op_white |
| 274 | BitwiseOpTok | 274 | BitwiseOpTok |
| 275 | <- AMPERSAND | 275 | <- AMPERSAND ![&] |
| 276 | / CARET | 276 | / CARET |
| 277 | / PIPE | 277 | / PIPE |
| 278 | / KEYWORD_orelse | 278 | / KEYWORD_orelse |
lib/std/zig/parser_fuzz.zig+6| ... | @@ -30,6 +30,12 @@ test "doc comment or division operator" { | ... | @@ -30,6 +30,12 @@ test "doc comment or division operator" { |
| 30 | try checkAgainstOracle("0=0///\n0"); | 30 | try checkAgainstOracle("0=0///\n0"); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | // Found using AFL++ | ||
| 34 | test "double ampersand" { | ||
| 35 | try checkAgainstOracle("0=0&&0"); // error | ||
| 36 | try checkAgainstOracle("test{&&0;}"); // ok | ||
| 37 | } | ||
| 38 | |||
| 33 | fn checkAgainstOracle(source: [:0]const u8) !void { | 39 | fn checkAgainstOracle(source: [:0]const u8) !void { |
| 34 | var fba_buf: [1 << 18]u8 = undefined; | 40 | var fba_buf: [1 << 18]u8 = undefined; |
| 35 | var fba: std.heap.FixedBufferAllocator = .init(&fba_buf); | 41 | var fba: std.heap.FixedBufferAllocator = .init(&fba_buf); |
lib/std/zig/parser_generated_oracle.zig+13-1| ... | @@ -1528,7 +1528,19 @@ const Parser = struct { | ... | @@ -1528,7 +1528,19 @@ const Parser = struct { |
| 1528 | pub fn parseBitwiseOpTok(p: *Parser) bool { | 1528 | pub fn parseBitwiseOpTok(p: *Parser) bool { |
| 1529 | return blk_0: { | 1529 | return blk_0: { |
| 1530 | const pos_0 = p.i; | 1530 | const pos_0 = p.i; |
| 1531 | if (p.parseAMPERSAND()) break :blk_0 true; | 1531 | if (p.parseAMPERSAND() and blk_1: { |
| 1532 | const pos_1 = p.i; | ||
| 1533 | const match_1 = (p.i < p.source.len and switch (p.source[p.i]) { | ||
| 1534 | '&'...'&', | ||
| 1535 | => blk_2: { | ||
| 1536 | p.i += 1; | ||
| 1537 | break :blk_2 true; | ||
| 1538 | }, | ||
| 1539 | else => false, | ||
| 1540 | }); | ||
| 1541 | p.i = pos_1; | ||
| 1542 | break :blk_1 !match_1; | ||
| 1543 | }) break :blk_0 true; | ||
| 1532 | p.i = pos_0; | 1544 | p.i = pos_0; |
| 1533 | if (p.parseCARET()) break :blk_0 true; | 1545 | if (p.parseCARET()) break :blk_0 true; |
| 1534 | p.i = pos_0; | 1546 | p.i = pos_0; |