authorgravatar for jan.bessai@tu-dortmund.deJan Bessai <jan.bessai@tu-dortmund.de> 2025-05-02 18:17:28+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-22 21:59:28-07:00
log0a01fe2bc6748b5fa2b03cebdcaae0e655501ad4
treec648ed74ca1bf11219dcc02cd5be84cb119831ab
parentfa4f5b26292dc1264a844815f60aacde7a3212a3

std.zig.Parse: fix and test off-by one in unreserveNode


1 files changed, 20 insertions(+), 1 deletions(-)

lib/std/zig/Parse.zig+20-1
...@@ -92,7 +92,7 @@ fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize {...@@ -92,7 +92,7 @@ fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize {
92}92}
9393
94fn unreserveNode(p: *Parse, node_index: usize) void {94fn unreserveNode(p: *Parse, node_index: usize) void {
95 if (p.nodes.len == node_index) {95 if (p.nodes.len == node_index + 1) {
96 p.nodes.resize(p.gpa, p.nodes.len - 1) catch unreachable;96 p.nodes.resize(p.gpa, p.nodes.len - 1) catch unreachable;
97 } else {97 } else {
98 // There is zombie node left in the tree, let's make it as inoffensive as possible98 // There is zombie node left in the tree, let's make it as inoffensive as possible
...@@ -3417,3 +3417,22 @@ const Token = std.zig.Token;...@@ -3417,3 +3417,22 @@ const Token = std.zig.Token;
3417test {3417test {
3418 _ = @import("parser_test.zig");3418 _ = @import("parser_test.zig");
3419}3419}
3420
3421test "unreserving a freshly reserved AST node must not create zombies" {
3422 const gpa = std.testing.allocator;
3423 var parser: Parse = .{
3424 .gpa = gpa,
3425 .nodes = .empty,
3426 .errors = .empty,
3427 .extra_data = .empty,
3428 .scratch = .empty,
3429 .source = "",
3430 .tok_i = 0,
3431 .tokens = undefined,
3432 .recover = false,
3433 };
3434 defer parser.nodes.deinit(gpa);
3435 const last = try parser.reserveNode(.@"try");
3436 parser.unreserveNode(last);
3437 try std.testing.expectEqual(parser.nodes.len, 0);
3438}