1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

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 d848a94998.
Fixes #35631.
This commit is contained in:
Yu Watanabe 2024-12-16 16:25:00 +09:00
parent 9bc2acad8f
commit a763364cc9

View File

@ -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();
}