Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

safety related fixes #1711

Merged
merged 5 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
self.bound_type_params.deinit(self.gpa);
self.resolved_callsites.deinit(self.gpa);
self.resolved_nodes.deinit(self.gpa);
std.debug.assert(self.use_trail.count() == 0);
self.use_trail.deinit(self.gpa);
self.arena.deinit();
}
Expand Down Expand Up @@ -493,6 +494,7 @@
const resolved = switch (node_tags[node_handle.node]) {
.identifier => blk: {
const name_token = main_tokens[node_handle.node];
if (tree.tokens.items(.tag)[name_token] != .identifier) break :blk null;
const name = offsets.identifierTokenToNameSlice(tree, name_token);
break :blk try analyser.lookupSymbolGlobal(
handle,
Expand Down Expand Up @@ -1871,7 +1873,10 @@
.error_union,
.union_tag,
=> |t| t.hashWithHasher(hasher),
.other => |idx| std.hash.autoHash(hasher, idx),
.other => |node_handle| {
std.hash.autoHash(hasher, node_handle.node);
hasher.update(node_handle.handle.uri);
},
.either => |entries| {
for (entries) |entry| {
hasher.update(entry.descriptor);
Expand Down Expand Up @@ -2466,7 +2471,10 @@
return if (field.tuple_like) null else tree.tokenSlice(field.main_token);
},
.error_value => tree.tokenSlice(data[node].rhs),
.identifier => offsets.identifierTokenToNameSlice(tree, main_token),
.identifier => {
if (tree.tokens.items(.tag)[main_token] != .identifier) return null;
return offsets.identifierTokenToNameSlice(tree, main_token);

Check warning on line 2476 in src/analysis.zig

View check run for this annotation

Codecov / codecov/patch

src/analysis.zig#L2475-L2476

Added lines #L2475 - L2476 were not covered by tests
},
.fn_proto,
.fn_proto_multi,
.fn_proto_one,
Expand Down Expand Up @@ -3182,7 +3190,7 @@
} else null;
}

fn iterateSymbolsContainerInternal(
pub fn iterateSymbolsContainer(
analyser: *Analyser,
container_handle: NodeWithHandle,
orig_handle: *DocumentStore.Handle,
Expand Down Expand Up @@ -3269,6 +3277,7 @@
) !void {
const gop = try analyser.use_trail.getOrPut(analyser.gpa, .{ .node = usingnamespace_node.node, .uri = usingnamespace_node.handle.uri });
if (gop.found_existing) return;
defer std.debug.assert(analyser.use_trail.remove(.{ .node = usingnamespace_node.node, .uri = usingnamespace_node.handle.uri }));

Check warning on line 3280 in src/analysis.zig

View check run for this annotation

Codecov / codecov/patch

src/analysis.zig#L3280

Added line #L3280 was not covered by tests

const handle = usingnamespace_node.handle;
const tree = handle.tree;
Expand All @@ -3284,7 +3293,7 @@

switch (use_expr.data) {
.other => |expr| {
try analyser.iterateSymbolsContainerInternal(
try analyser.iterateSymbolsContainer(
expr,
orig_handle,
callback,
Expand All @@ -3296,7 +3305,7 @@
for (entries) |entry| {
switch (entry.type_with_handle.data) {
.other => |expr| {
try analyser.iterateSymbolsContainerInternal(
try analyser.iterateSymbolsContainer(
expr,
orig_handle,
callback,
Expand Down Expand Up @@ -3339,18 +3348,6 @@
};
}

pub fn iterateSymbolsContainer(
analyser: *Analyser,
container_handle: NodeWithHandle,
orig_handle: *DocumentStore.Handle,
comptime callback: anytype,
context: anytype,
instance_access: bool,
) error{OutOfMemory}!void {
analyser.use_trail.clearRetainingCapacity();
return try analyser.iterateSymbolsContainerInternal(container_handle, orig_handle, callback, context, instance_access);
}

pub fn iterateLabels(handle: *DocumentStore.Handle, source_index: usize, comptime callback: anytype, context: anytype) error{OutOfMemory}!void {
const document_scope = try handle.getDocumentScope();
var scope_iterator = iterateEnclosingScopes(&document_scope, source_index);
Expand Down Expand Up @@ -3449,10 +3446,10 @@
}

fn resolveUse(analyser: *Analyser, uses: []const Ast.Node.Index, symbol: []const u8, handle: *DocumentStore.Handle) error{OutOfMemory}!?DeclWithHandle {
analyser.use_trail.clearRetainingCapacity();
for (uses) |index| {
const gop = try analyser.use_trail.getOrPut(analyser.gpa, .{ .node = index, .uri = handle.uri });
if (gop.found_existing) continue;
defer std.debug.assert(analyser.use_trail.remove(.{ .node = index, .uri = handle.uri }));

const tree = handle.tree;
if (tree.nodes.items(.data).len <= index) continue;
Expand Down Expand Up @@ -4360,6 +4357,7 @@
const tree = handle.tree;

const name_token = tree.nodes.items(.main_token)[node];
if (tree.tokens.items(.tag)[name_token] != .identifier) return null;

Check warning on line 4360 in src/analysis.zig

View check run for this annotation

Codecov / codecov/patch

src/analysis.zig#L4360

Added line #L4360 was not covered by tests
const name = offsets.identifierTokenToNameSlice(tree, name_token);
const is_escaped_identifier = tree.source[tree.tokens.items(.start)[name_token]] == '@';
if (is_escaped_identifier) return null;
Expand Down
2 changes: 1 addition & 1 deletion src/features/inlay_hints.zig
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ fn writeForCaptureHint(builder: *Builder, for_node: Ast.Node.Index) !void {
defer tracy_zone.end();

const tree = builder.handle.tree;
const full_for = tree.fullFor(for_node).?;
const full_for = ast.fullFor(tree, for_node).?;
const token_tags = tree.tokens.items(.tag);
var capture_token = full_for.payload_token;
for (full_for.ast.inputs) |_| {
Expand Down
7 changes: 6 additions & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ fn updateConfig(
const json_message = try transport.readJsonMessage(allocator);
defer allocator.free(json_message);

const new_config = try std.json.parseFromSlice(Config, allocator, json_message, .{});
const new_config = try std.json.parseFromSlice(
Config,
allocator,
json_message,
.{ .allocate = .alloc_always },
);
defer allocator.destroy(new_config.arena);
config.arena.promote(allocator).deinit();
config.arena = new_config.arena.state;
Expand Down
16 changes: 16 additions & 0 deletions tests/lsp_features/semantic_tokens.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,22 @@ test "semantic tokens - assembly" {
});
}

test "semantic tokens - recursive usingnamespace" {
// this test is supposed to check against infinite recursion when resolving usingnamespace
try testSemanticTokens(
\\const A = struct {
\\ usingnamespace A;
\\};
, &.{
.{ "const", .keyword, .{} },
.{ "A", .namespace, .{ .declaration = true } },
.{ "=", .operator, .{} },
.{ "struct", .keyword, .{} },
.{ "usingnamespace", .keyword, .{} },
.{ "A", .namespace, .{} },
});
}

test "semantic tokens - weird code" {
// the expected output is irrelevant, just ensure no crash
try testSemanticTokens(
Expand Down