authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-06-18 14:20:39+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 11:48:59+02:00
logec04ae6e0003a7fd35782dbc26c89f9905119aee
treedf7bc6096d797624c4bf17086f02763b75f8c4bd
parentd9c6669f72c6d6d12a6533282c07239deac0c9c7
signaturelock-open Commit is signed but in an unrecognized format.

grammar: fix tokenization of @"" strings


3 files changed, 24 insertions(+), 7 deletions(-)

doc/langref/grammar.peg+4-3
......@@ -527,13 +527,14 @@ NUMBERLITERAL
527527 / skip [0-9] digit_float*
528528
529529
530STRINGLITERALSINGLE <- skip ["] string_char* ["]
530string <- ["] string_char* ["]
531STRINGLITERALSINGLE <- skip string
531532STRINGLITERAL
532 <- STRINGLITERALSINGLE
533 <- skip string
533534 / (skip line_string)+
534535IDENTIFIER
535536 <- skip !keyword [A-Za-z_] [A-Za-z0-9_]*
536 / skip '@' STRINGLITERALSINGLE
537 / skip '@' string
537538BUILTINIDENTIFIER <- skip '@'[A-Za-z_][A-Za-z0-9_]*
538539
539540
lib/std/zig/parser_fuzz.zig+8
......@@ -78,6 +78,14 @@ test "fn container field" {
7878 try checkAgainstOracle("fn()0");
7979}
8080
81// Found using AFL++
82test "at newline string" {
83 try checkAgainstOracle(
84 \\@
85 \\""
86 );
87}
88
8189fn checkAgainstOracle(source: [:0]const u8) !void {
8290 var fba_buf: [1 << 18]u8 = undefined;
8391 var fba: std.heap.FixedBufferAllocator = .init(&fba_buf);
lib/std/zig/parser_generated_oracle.zig+12-4
......@@ -2818,10 +2818,10 @@ const Parser = struct {
28182818 break :blk_0 false;
28192819 };
28202820 }
2821 pub fn parseSTRINGLITERALSINGLE(p: *Parser) bool {
2821 pub fn parsestring(p: *Parser) bool {
28222822 return blk_0: {
28232823 const pos_0 = p.i;
2824 if (p.parseskip() and (p.i < p.source.len and switch (p.source[p.i]) {
2824 if ((p.i < p.source.len and switch (p.source[p.i]) {
28252825 '"'...'"',
28262826 => blk_1: {
28272827 p.i += 1;
......@@ -2843,10 +2843,18 @@ const Parser = struct {
28432843 break :blk_0 false;
28442844 };
28452845 }
2846 pub fn parseSTRINGLITERALSINGLE(p: *Parser) bool {
2847 return blk_0: {
2848 const pos_0 = p.i;
2849 if (p.parseskip() and p.parsestring()) break :blk_0 true;
2850 p.i = pos_0;
2851 break :blk_0 false;
2852 };
2853 }
28462854 pub fn parseSTRINGLITERAL(p: *Parser) bool {
28472855 return blk_0: {
28482856 const pos_0 = p.i;
2849 if (p.parseSTRINGLITERALSINGLE()) break :blk_0 true;
2857 if (p.parseskip() and p.parsestring()) break :blk_0 true;
28502858 p.i = pos_0;
28512859 if (blk_1: {
28522860 var match_1 = false;
......@@ -2902,7 +2910,7 @@ const Parser = struct {
29022910 break :blk_1 true;
29032911 }
29042912 break :blk_1 false;
2905 } and p.parseSTRINGLITERALSINGLE()) break :blk_0 true;
2913 } and p.parsestring()) break :blk_0 true;
29062914 p.i = pos_0;
29072915 break :blk_0 false;
29082916 };