From: Yu Watanabe Date: Mon, 16 Dec 2024 07:25:00 +0000 (+0900) Subject: ptyfwd: fix logic of OSC sequence termination X-Git-Tag: v258-rc1~1847^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F35640%2Fhead;p=thirdparty%2Fsystemd.git 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. --- 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(); }