mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-11 03:39:36 +00:00
terminal: reserve title terminator atomically
setTitle appended the title bytes and terminating NUL with separate fallible operations. If only the terminator allocation failed, it returned OutOfMemory but left a nonempty unterminated buffer that made getTitle panic on its sentinel check. Reserve checked capacity before clearing the existing title, then append both the title and terminator without further allocation. Allocation failure now leaves the prior valid title intact.
This commit is contained in:
@@ -3591,11 +3591,18 @@ test "Terminal: setPwd preserves a sentinel on allocation failure" {
|
||||
|
||||
/// Set the title for the terminal, as set by escape sequences (e.g. OSC 0/2).
|
||||
pub fn setTitle(self: *Terminal, t: []const u8) !void {
|
||||
self.title.clearRetainingCapacity();
|
||||
if (t.len > 0) {
|
||||
try self.title.appendSlice(self.gpa(), t);
|
||||
try self.title.append(self.gpa(), 0);
|
||||
if (t.len == 0) {
|
||||
self.title.clearRetainingCapacity();
|
||||
return;
|
||||
}
|
||||
|
||||
const capacity = std.math.add(usize, t.len, 1) catch
|
||||
return error.OutOfMemory;
|
||||
try self.title.ensureTotalCapacity(self.gpa(), capacity);
|
||||
|
||||
self.title.clearRetainingCapacity();
|
||||
self.title.appendSliceAssumeCapacity(t);
|
||||
self.title.appendAssumeCapacity(0);
|
||||
}
|
||||
|
||||
/// Returns the title for the terminal, if any. The memory is owned by the
|
||||
@@ -3605,6 +3612,18 @@ pub fn getTitle(self: *const Terminal) ?[:0]const u8 {
|
||||
return self.title.items[0 .. self.title.items.len - 1 :0];
|
||||
}
|
||||
|
||||
test "Terminal: setTitle preserves a sentinel on allocation failure" {
|
||||
var failing = testing.FailingAllocator.init(testing.allocator, .{});
|
||||
const alloc = failing.allocator();
|
||||
var t = try init(alloc, .{ .cols = 5, .rows = 1 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
try t.title.ensureTotalCapacityPrecise(alloc, 5);
|
||||
failing.fail_index = failing.alloc_index;
|
||||
try testing.expectError(error.OutOfMemory, t.setTitle("title"));
|
||||
try testing.expect(t.getTitle() == null);
|
||||
}
|
||||
|
||||
/// Switch to the given screen type (alternate or primary).
|
||||
///
|
||||
/// This does NOT handle behaviors such as clearing the screen,
|
||||
|
||||
Reference in New Issue
Block a user