mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-11 03:39:36 +00:00
terminal: duplicate hyperlinks before replacement
startHyperlink accepts borrowed URI and ID slices. When those slices came from the current cursor hyperlink, startHyperlinkOnce ended and freed that hyperlink before duplicating the replacement, then dereferenced the released URI and segfaulted. Duplicate the new hyperlink before ending the prior one. Aliased inputs remain valid through the copy, and allocation failure leaves the existing cursor hyperlink intact.
This commit is contained in:
@@ -2460,9 +2460,6 @@ fn startHyperlinkOnce(
|
||||
self: *Screen,
|
||||
source: hyperlink.Hyperlink,
|
||||
) (Allocator.Error || Page.InsertHyperlinkError)!void {
|
||||
// End any prior hyperlink
|
||||
self.endHyperlink();
|
||||
|
||||
// Allocate our new Hyperlink entry in non-page memory. This
|
||||
// lets us quickly get access to URI, ID.
|
||||
const link = try self.alloc.create(hyperlink.Hyperlink);
|
||||
@@ -2470,6 +2467,10 @@ fn startHyperlinkOnce(
|
||||
link.* = try source.dupe(self.alloc);
|
||||
errdefer link.deinit(self.alloc);
|
||||
|
||||
// End any prior hyperlink only after duplicating the new value. The
|
||||
// source slices are allowed to reference our current hyperlink.
|
||||
self.endHyperlink();
|
||||
|
||||
// Insert the hyperlink into page memory
|
||||
var page = self.cursor.page_pin.node.page();
|
||||
const id: hyperlink.Id = try page.insertHyperlink(link.*);
|
||||
@@ -10033,6 +10034,21 @@ test "Screen: hyperlink start/end" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Screen: hyperlink accepts its current values" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
var s = try init(alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 });
|
||||
defer s.deinit();
|
||||
|
||||
try s.startHyperlink("http://example.com", "current");
|
||||
const current = s.cursor.hyperlink.?;
|
||||
try s.startHyperlink(current.uri, current.id.explicit);
|
||||
|
||||
try testing.expectEqualStrings("http://example.com", s.cursor.hyperlink.?.uri);
|
||||
try testing.expectEqualStrings("current", s.cursor.hyperlink.?.id.explicit);
|
||||
}
|
||||
|
||||
test "Screen: implicit hyperlink ID wraps" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
Reference in New Issue
Block a user