mirror of
https://github.com/ziglang/zig.git
synced 2026-01-28 02:05:31 +00:00
Bug fix: Prevent uninitialized parse nodes
If a parse node is reserved but never set the node remains uninitialized and can crash tools doing a linear scan of the nodes (like ZLS) when switching on the tag.
This commit is contained in:
parent
30eb2a1753
commit
f61c5f3f52
@ -131,11 +131,23 @@ const Parser = struct {
|
||||
return @intCast(Node.Index, i);
|
||||
}
|
||||
|
||||
fn reserveNode(p: *Parser) !usize {
|
||||
fn reserveNode(p: *Parser, tag: Ast.Node.Tag) !usize {
|
||||
try p.nodes.resize(p.gpa, p.nodes.len + 1);
|
||||
p.nodes.items(.tag)[p.nodes.len - 1] = tag;
|
||||
return p.nodes.len - 1;
|
||||
}
|
||||
|
||||
fn unreserveNode(p: *Parser, node_index: usize) void {
|
||||
if (p.nodes.len == node_index) {
|
||||
p.nodes.resize(p.gpa, p.nodes.len - 1) catch unreachable;
|
||||
} else {
|
||||
// There is zombie node left in the tree, let's make it as inoffensive as possible
|
||||
// (sadly there's no no-op node)
|
||||
p.nodes.items(.tag)[node_index] = .unreachable_literal;
|
||||
p.nodes.items(.main_token)[node_index] = p.tok_i;
|
||||
}
|
||||
}
|
||||
|
||||
fn addExtra(p: *Parser, extra: anytype) Allocator.Error!Node.Index {
|
||||
const fields = std.meta.fields(@TypeOf(extra));
|
||||
try p.extra_data.ensureUnusedCapacity(p.gpa, fields.len);
|
||||
@ -637,13 +649,15 @@ const Parser = struct {
|
||||
return fn_proto;
|
||||
},
|
||||
.l_brace => {
|
||||
const fn_decl_index = try p.reserveNode();
|
||||
const body_block = try p.parseBlock();
|
||||
assert(body_block != 0);
|
||||
if (is_extern) {
|
||||
try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token });
|
||||
return null_node;
|
||||
}
|
||||
const fn_decl_index = try p.reserveNode(.fn_decl);
|
||||
errdefer p.unreserveNode(fn_decl_index);
|
||||
|
||||
const body_block = try p.parseBlock();
|
||||
assert(body_block != 0);
|
||||
return p.setNode(fn_decl_index, .{
|
||||
.tag = .fn_decl,
|
||||
.main_token = p.nodes.items(.main_token)[fn_proto],
|
||||
@ -724,7 +738,8 @@ const Parser = struct {
|
||||
const fn_token = p.eatToken(.keyword_fn) orelse return null_node;
|
||||
|
||||
// We want the fn proto node to be before its children in the array.
|
||||
const fn_proto_index = try p.reserveNode();
|
||||
const fn_proto_index = try p.reserveNode(.fn_proto);
|
||||
errdefer p.unreserveNode(fn_proto_index);
|
||||
|
||||
_ = p.eatToken(.identifier);
|
||||
const params = try p.parseParamDeclList();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user