From e45f002d1aaee91a9c17dd9293e4262ef608149e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 5 Jun 2026 13:14:01 -0700 Subject: [PATCH] terminal/apc: reject malformed glyph register input Register parsing now validates the full register request shape before constructing the parsed command. Inputs that only contain the verb separator, such as `r`, `r;cp=e0a0`, or `r;foo`, now fail with InvalidFormat instead of reaching Register invariants guarded by asserts. Valid empty-payload requests still parse when they include the payload separator, allowing execution to report malformed_payload through the normal protocol response path. --- src/terminal/apc/glyph/request.zig | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/terminal/apc/glyph/request.zig b/src/terminal/apc/glyph/request.zig index 6fecbc287..b33a28413 100644 --- a/src/terminal/apc/glyph/request.zig +++ b/src/terminal/apc/glyph/request.zig @@ -119,12 +119,12 @@ pub const Request = union(enum) { payload_idx: usize, /// Initialize a register command from owned raw command bytes. - pub fn init(raw: []const u8) Register { - assert(raw.len >= 2); - assert(raw[0] == 'r'); - assert(raw[1] == ';'); - const payload_idx = std.mem.lastIndexOfScalar(u8, raw, ';').?; - assert(payload_idx > 1); + pub fn init(raw: []const u8) ?Register { + if (raw.len < 2) return null; + if (raw[0] != 'r') return null; + if (raw[1] != ';') return null; + const payload_idx = std.mem.lastIndexOfScalar(u8, raw, ';') orelse return null; + if (payload_idx <= 1) return null; return .{ .raw = raw, @@ -395,7 +395,7 @@ pub const Request = union(enum) { return .support; }, 'q' => .{ .query = .init(raw) }, - 'r' => .{ .register = .init(raw) }, + 'r' => .{ .register = Register.init(raw) orelse return error.InvalidFormat }, 'c' => .{ .clear = .init(raw) }, else => error.InvalidFormat, }; @@ -765,6 +765,17 @@ test "register command with invalid payload" { try testing.expectEqualStrings("%%%not-base64%%%", cmd.register.payload()); } +test "register command rejects missing payload separator" { + const testing = std.testing; + + for ([_][]const u8{ "r", "r;cp=e0a0", "r;foo" }) |data| { + try testing.expectError( + error.InvalidFormat, + testParse(testing.allocator, data), + ); + } +} + test "register decodes glyf payload" { const testing = std.testing;