From 957ed21d5c6241f81526581db78520d3c3196421 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Mon, 3 Aug 2026 11:36:39 -0400 Subject: [PATCH] core: free allocated writes in read-only mode Read-only filtering happens in Surface.queueIo after callers construct the message. This early return leaked write_alloc payloads because the IO thread never receives them and therefore does not perform its normal cleanup. --- src/Surface.zig | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Surface.zig b/src/Surface.zig index f494f6c82..61aaa34d1 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -872,9 +872,13 @@ fn queueIo( switch (msg) { .write_small, .write_stable, - .write_alloc, => return, + .write_alloc => |v| { + v.alloc.free(v.data); + return; + }, + else => {}, } } @@ -6064,3 +6068,18 @@ fn presentSurface(self: *Surface) !void { pub fn getProcessInfo(self: *Surface, comptime info: ProcessInfo) ?ProcessInfo.Type(info) { return self.io.getProcessInfo(info); } + +test "queueIo frees allocated writes in readonly mode" { + const testing = std.testing; + + const surface = try testing.allocator.create(Surface); + defer testing.allocator.destroy(surface); + surface.readonly = true; + + // queueIo must free allocated writes in read-only mode. + const data = try testing.allocator.dupe(u8, "\x1b]lGhostty\x1b\\"); + surface.queueIo(.{ .write_alloc = .{ + .alloc = testing.allocator, + .data = data, + } }, .unlocked); +}