From 5e800df27798dbd88de1c74eb0feb6642e963185 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Thu, 21 Sep 2023 01:58:19 -0500 Subject: [PATCH] osc: allow 0x20-0xFF in osc_put The osc_string state of the parser limited accepted bytes to 0x7F. When parsing a utf-8 encoded string as part of an OSC string, the parser would encounter an error and abort the OSC parsing, allowing any remaining bytes to be leaked (possibly) as printable characters to the terminal window. Allow any byte in the range 0x20 - 0xFF to be accepted by osc_put. Add test cases which conflict with the 'anywhere' transitions (IE the utf8 sequence includes C1 control codes which might transition to another state). --- src/terminal/osc.zig | 22 ++++++++++++++++++++++ src/terminal/parse_table.zig | 9 +++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/terminal/osc.zig b/src/terminal/osc.zig index 03d3baf99..c8f42b66a 100644 --- a/src/terminal/osc.zig +++ b/src/terminal/osc.zig @@ -584,6 +584,28 @@ test "OSC: change_window_title with 2" { try testing.expectEqualStrings("ab", cmd.change_window_title); } +test "OSC: change_window_title with utf8" { + const testing = std.testing; + + var p: Parser = .{}; + p.next('2'); + p.next(';'); + // '—' EM DASH U+2014 (E2 80 94) + p.next(0xE2); + p.next(0x80); + p.next(0x94); + + p.next(' '); + // '‐' HYPHEN U+2010 (E2 80 90) + // Intententionally chosen to conflict with the 0x90 C1 control + p.next(0xE2); + p.next(0x80); + p.next(0x90); + const cmd = p.end(null).?; + try testing.expect(cmd == .change_window_title); + try testing.expectEqualStrings("— ‐", cmd.change_window_title); +} + test "OSC: prompt_start" { const testing = std.testing; diff --git a/src/terminal/parse_table.zig b/src/terminal/parse_table.zig index 094128cc7..e7542b062 100644 --- a/src/terminal/parse_table.zig +++ b/src/terminal/parse_table.zig @@ -345,7 +345,7 @@ fn genTable() Table { range(&result, 0, 0x06, source, source, .ignore); range(&result, 0x08, 0x17, source, source, .ignore); range(&result, 0x1C, 0x1F, source, source, .ignore); - range(&result, 0x20, 0x7F, source, source, .osc_put); + range(&result, 0x20, 0xFF, source, source, .osc_put); // XTerm accepts either BEL or ST for terminating OSC // sequences, and when returning information, uses the same @@ -381,7 +381,12 @@ fn single(t: *OptionalTable, c: u8, s0: State, s1: State, a: Action) void { fn range(t: *OptionalTable, from: u8, to: u8, s0: State, s1: State, a: Action) void { var i = from; - while (i <= to) : (i += 1) single(t, i, s0, s1, a); + while (i <= to) : (i += 1) { + single(t, i, s0, s1, a); + // If 'to' is 0xFF, our next pass will overflow. Return early to prevent + // the loop from executing it's continue expression + if (i == to) break; + } } fn transition(state: State, action: Action) Transition {