repos / zmx

session persistence for terminal processes
git clone https://github.com/neurosnap/zmx.git

commit
a466e75
parent
52dda8a
author
Eric Bower
date
2025-10-13 14:40:41 -0400 EDT
refactor: remove sanitized buffer for now
1 files changed,  +7, -29
M src/daemon.zig
+7, -29
 1@@ -810,51 +810,29 @@ fn readPtyCallback(
 2             return .disarm;
 3         }
 4 
 5-        const total_len = bytes_read;
 6         const data = read_buffer.slice[0..bytes_read];
 7         std.debug.print("PTY output ({d} bytes)\n", .{bytes_read});
 8 
 9-        // Build a sanitized buffer that only includes bytes we can safely send
10-        var sanitized_buf = std.ArrayList(u8).initCapacity(session.allocator, total_len) catch return .disarm;
11-        defer sanitized_buf.deinit(session.allocator);
12-
13-        // Parse through libghostty-vt byte-by-byte to handle invalid data
14-        // This is necessary because binary data (like /dev/urandom) can cause
15-        // panics in @enumFromInt when high bytes appear during escape sequences
16-        for (data) |byte| {
17-            // Skip high bytes when parser is not in ground state to avoid
18-            // @enumFromInt panic in execute() which expects u7 (0-127)
19-            if (session.vt_stream.parser.state != .ground and byte > 127) {
20-                // Reset to ground state and skip this byte
21-                session.vt_stream.parser.state = .ground;
22-                continue;
23-            }
24-            session.vt_stream.next(byte) catch |err| {
25-                std.debug.print("VT parse error at byte 0x{x}: {s}\n", .{ byte, @errorName(err) });
26-                // Reset to ground state on any error
27-                session.vt_stream.parser.state = .ground;
28-                continue;
29-            };
30-            // Only add to sanitized buffer if we successfully parsed it
31-            sanitized_buf.append(session.allocator, byte) catch {};
32-        }
33+        session.vt_stream.nextSlice(data) catch |err| {
34+            std.debug.print("VT parse error: {s}\n", .{@errorName(err)});
35+        };
36 
37         // Only proxy to clients if someone is attached
38-        if (session.attached_clients.count() > 0 and sanitized_buf.items.len > 0) {
39+        if (session.attached_clients.count() > 0 and data.len > 0) {
40             // Send PTY output as binary frame to avoid JSON escaping issues
41             // Frame format: [4-byte length][2-byte type][payload]
42             const header = protocol.FrameHeader{
43-                .length = @intCast(sanitized_buf.items.len),
44+                .length = @intCast(data.len),
45                 .frame_type = @intFromEnum(protocol.FrameType.pty_binary),
46             };
47 
48             // Build complete frame with header + payload
49-            var frame_buf = std.ArrayList(u8).initCapacity(session.allocator, @sizeOf(protocol.FrameHeader) + sanitized_buf.items.len) catch return .disarm;
50+            var frame_buf = std.ArrayList(u8).initCapacity(session.allocator, @sizeOf(protocol.FrameHeader) + data.len) catch return .disarm;
51             defer frame_buf.deinit(session.allocator);
52 
53             const header_bytes = std.mem.asBytes(&header);
54             frame_buf.appendSlice(session.allocator, header_bytes) catch return .disarm;
55-            frame_buf.appendSlice(session.allocator, sanitized_buf.items) catch return .disarm;
56+            frame_buf.appendSlice(session.allocator, data) catch return .disarm;
57 
58             // Send to all attached clients using async write
59             var it = session.attached_clients.keyIterator();