Skip to content

Commit d4ae20b

Browse files
rabbitkasper93
authored andcommitted
msg: sanitize term title and block C1 controls and DEL
Expose the terminal output sanitizer as mp_msg_sanitize() and use it in term_osd_update_title() to sanitize the property-expanded term-title string before it reaches mp_msg_set_term_title(). Without this, a crafted media tag can break out of the OSC-0 sequence via embedded BEL or ESC bytes when --term-title includes property expansions like ${media-title}. Extend the sanitizer to cover two gaps: - UTF-8 encoded C1 controls (U+0080-U+009F, bytes C2 80..C2 9F). xterm in UTF-8 mode interprets these codepoints as C1 control functions (U+009B as CSI, U+009D as OSC, U+009C as ST), allowing escape sequence injection without any ESC or BEL bytes. - DEL (0x7F), which was not previously filtered.
1 parent 4d06666 commit d4ae20b

3 files changed

Lines changed: 21 additions & 4 deletions

File tree

common/msg.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ static void write_term_msg(struct mp_log *log, int lev, bstr text, bstr *out)
559559
}
560560
}
561561

562-
static void sanitize(bstr *text)
562+
void mp_msg_sanitize(bstr *text)
563563
{
564564
for (size_t i = 0; i < text->len; i++) {
565565
unsigned char ch = text->start[i];
@@ -587,9 +587,20 @@ static void sanitize(bstr *text)
587587
text->start[i] = '?';
588588
}
589589
// Allow only printable > 0x20 and 0x08-0x0D (backspace, tab, newline, ...)
590-
else if (ch < 0x08 || (ch > 0x0D && ch < 0x20)) {
590+
else if (ch < 0x08 || (ch > 0x0D && ch < 0x20) || ch == 0x7F) {
591591
text->start[i] = '?';
592592
}
593+
// Block UTF-8 encoded C1 controls (U+0080-U+009F = bytes C2 80..C2 9F).
594+
// xterm interprets these as C1 control functions (CSI, OSC, DCS, ST, ...),
595+
// which allows bypassing the ESC/BEL filter above.
596+
else if (ch == 0xC2 && i + 1 < text->len &&
597+
(unsigned char)text->start[i + 1] >= 0x80 &&
598+
(unsigned char)text->start[i + 1] <= 0x9F)
599+
{
600+
text->start[i] = '?';
601+
text->start[i + 1] = '?';
602+
i++;
603+
}
593604
}
594605
}
595606

@@ -613,7 +624,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
613624
bstr_xappend(root, &root->buffer, bstr0(format));
614625
}
615626

616-
sanitize(&root->buffer);
627+
mp_msg_sanitize(&root->buffer);
617628

618629
// Remember last status message and restore it to ensure that it is
619630
// always displayed

common/msg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ static inline bool mp_msg_test(struct mp_log *log, int lev)
6767

6868
void mp_msg_set_max_level(struct mp_log *log, int lev);
6969

70+
// Sanitize text for terminal output.
71+
struct bstr;
72+
void mp_msg_sanitize(struct bstr *text);
73+
7074
// Convenience macros.
7175
#define mp_fatal(log, ...) mp_msg(log, MSGL_FATAL, __VA_ARGS__)
7276
#define mp_err(log, ...) mp_msg(log, MSGL_ERR, __VA_ARGS__)

player/osd.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ static void term_osd_update_title(struct MPContext *mpctx)
108108
return;
109109

110110
char *s = mp_property_expand_escaped_string(mpctx, mpctx->opts->term_title);
111-
if (bstr_equals(bstr0(s), bstr0(mpctx->term_osd_title))) {
111+
bstr title = bstr0(s);
112+
mp_msg_sanitize(&title);
113+
if (bstr_equals(title, bstr0(mpctx->term_osd_title))) {
112114
talloc_free(s);
113115
return;
114116
}

0 commit comments

Comments
 (0)