From a763364cc9183d72d7527ebf9ef853f99966bd5e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 16 Dec 2024 16:25:00 +0900 Subject: [PATCH] ptyfwd: fix logic of OSC sequence termination Previously, when an OSC sequence is terminated with \x1b\x5c, configured OSC sequence would be inserted between the two characters, rather than after the two. Fixes a bug introduced by d848a9499830c530e804a41ffd8aa1bc942fa735. Fixes #35631. --- src/shared/ptyfwd.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 331d092c63b..00450ca6967 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -36,6 +36,7 @@ typedef enum AnsiColorState { ANSI_COLOR_STATE_ESC, ANSI_COLOR_STATE_CSI_SEQUENCE, ANSI_COLOR_STATE_OSC_SEQUENCE, + ANSI_COLOR_STATE_OSC_SEQUENCE_TERMINATING, _ANSI_COLOR_STATE_MAX, _ANSI_COLOR_STATE_INVALID = -EINVAL, } AnsiColorState; @@ -501,33 +502,46 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) { f->ansi_color_state = ANSI_COLOR_STATE_TEXT; } else if (!strextend(&f->osc_sequence, CHAR_TO_STR(c))) return -ENOMEM; - } else { + } else if (c == '\x07') { /* Otherwise, the OSC sequence is over * * There are three documented ways to end an OSC sequence: * 1. BEL aka ^G aka \x07 * 2. \x9c * 3. \x1b\x5c - * since we cannot look ahead to see if the Esc is followed by a "\" - * we cut a corner here and assume it will be "\"e. - * * Note that we do not support \x9c here, because that's also a valid UTF8 * codepoint, and that would create ambiguity. Various terminal emulators * similar do not support it. */ - if (IN_SET(c, '\x07', '\x1b')) { - r = insert_window_title_fix(f, i+1); - if (r < 0) - return r; - - i += r; - } + r = insert_window_title_fix(f, i+1); + if (r < 0) + return r; + i += r; + f->osc_sequence = mfree(f->osc_sequence); + f->ansi_color_state = ANSI_COLOR_STATE_TEXT; + } else if (c == '\x1b') + /* See the comment above. */ + f->ansi_color_state = ANSI_COLOR_STATE_OSC_SEQUENCE_TERMINATING; + else { + /* Unexpected or unsupported OSC sequence. */ f->osc_sequence = mfree(f->osc_sequence); f->ansi_color_state = ANSI_COLOR_STATE_TEXT; } break; + case ANSI_COLOR_STATE_OSC_SEQUENCE_TERMINATING: + if (c == '\x5c') { + r = insert_window_title_fix(f, i+1); + if (r < 0) + return r; + i += r; + } + + f->osc_sequence = mfree(f->osc_sequence); + f->ansi_color_state = ANSI_COLOR_STATE_TEXT; + break; + default: assert_not_reached(); }