mirror of
https://github.com/mpv-player/mpv.git
synced 2026-05-07 20:02:49 +00:00
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.
This commit is contained in:
+14
-3
@@ -559,7 +559,7 @@ static void write_term_msg(struct mp_log *log, int lev, bstr text, bstr *out)
|
||||
}
|
||||
}
|
||||
|
||||
static void sanitize(bstr *text)
|
||||
void mp_msg_sanitize(bstr *text)
|
||||
{
|
||||
for (size_t i = 0; i < text->len; i++) {
|
||||
unsigned char ch = text->start[i];
|
||||
@@ -587,9 +587,20 @@ static void sanitize(bstr *text)
|
||||
text->start[i] = '?';
|
||||
}
|
||||
// Allow only printable > 0x20 and 0x08-0x0D (backspace, tab, newline, ...)
|
||||
else if (ch < 0x08 || (ch > 0x0D && ch < 0x20)) {
|
||||
else if (ch < 0x08 || (ch > 0x0D && ch < 0x20) || ch == 0x7F) {
|
||||
text->start[i] = '?';
|
||||
}
|
||||
// Block UTF-8 encoded C1 controls (U+0080-U+009F = bytes C2 80..C2 9F).
|
||||
// xterm interprets these as C1 control functions (CSI, OSC, DCS, ST, ...),
|
||||
// which allows bypassing the ESC/BEL filter above.
|
||||
else if (ch == 0xC2 && i + 1 < text->len &&
|
||||
(unsigned char)text->start[i + 1] >= 0x80 &&
|
||||
(unsigned char)text->start[i + 1] <= 0x9F)
|
||||
{
|
||||
text->start[i] = '?';
|
||||
text->start[i + 1] = '?';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +624,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
|
||||
bstr_xappend(root, &root->buffer, bstr0(format));
|
||||
}
|
||||
|
||||
sanitize(&root->buffer);
|
||||
mp_msg_sanitize(&root->buffer);
|
||||
|
||||
// Remember last status message and restore it to ensure that it is
|
||||
// always displayed
|
||||
|
||||
@@ -67,6 +67,10 @@ static inline bool mp_msg_test(struct mp_log *log, int lev)
|
||||
|
||||
void mp_msg_set_max_level(struct mp_log *log, int lev);
|
||||
|
||||
// Sanitize text for terminal output.
|
||||
struct bstr;
|
||||
void mp_msg_sanitize(struct bstr *text);
|
||||
|
||||
// Convenience macros.
|
||||
#define mp_fatal(log, ...) mp_msg(log, MSGL_FATAL, __VA_ARGS__)
|
||||
#define mp_err(log, ...) mp_msg(log, MSGL_ERR, __VA_ARGS__)
|
||||
|
||||
+3
-1
@@ -108,7 +108,9 @@ static void term_osd_update_title(struct MPContext *mpctx)
|
||||
return;
|
||||
|
||||
char *s = mp_property_expand_escaped_string(mpctx, mpctx->opts->term_title);
|
||||
if (bstr_equals(bstr0(s), bstr0(mpctx->term_osd_title))) {
|
||||
bstr title = bstr0(s);
|
||||
mp_msg_sanitize(&title);
|
||||
if (bstr_equals(title, bstr0(mpctx->term_osd_title))) {
|
||||
talloc_free(s);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user