1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 11:37:44 +00:00

LibVT: Always check intermediate bytes in CSI sequences

Previously, we only checked the intermediate bytes for those escape
sequences that performed different operations based on their
intermediate bytes. This lead to a crash when `CSI ?1001 r` was
incorrectly parsed as `CSI Pt ; Pb r` (note the missing question mark),
as seen in #8559.
This commit is contained in:
Daniel Bertalan 2021-07-09 12:08:36 +02:00 committed by Ali Mohammad Pur
parent 52aa777d49
commit 0e04f7cf1e
2 changed files with 201 additions and 213 deletions

View file

@ -48,7 +48,19 @@ void Terminal::clear_history()
} }
#endif #endif
void Terminal::alter_mode(bool should_set, Parameters params, Intermediates intermediates) void Terminal::alter_ansi_mode(bool should_set, Parameters params)
{
for (auto mode : params) {
switch (mode) {
// FIXME: implement *something* for this
default:
dbgln("Terminal::alter_ansi_mode: Unimplemented mode {} (should_set={})", mode, should_set);
break;
}
}
}
void Terminal::alter_private_mode(bool should_set, Parameters params)
{ {
auto steady_cursor_to_blinking = [](CursorStyle style) { auto steady_cursor_to_blinking = [](CursorStyle style) {
switch (style) { switch (style) {
@ -76,107 +88,106 @@ void Terminal::alter_mode(bool should_set, Parameters params, Intermediates inte
} }
}; };
if (intermediates.size() > 0 && intermediates[0] == '?') { for (auto mode : params) {
for (auto mode : params) { switch (mode) {
switch (mode) { case 3: {
case 3: { // 80/132-column mode (DECCOLM)
// 80/132-column mode (DECCOLM) unsigned new_columns = should_set ? 132 : 80;
unsigned new_columns = should_set ? 132 : 80; dbgln_if(TERMINAL_DEBUG, "Setting {}-column mode", new_columns);
dbgln_if(TERMINAL_DEBUG, "Setting {}-column mode", new_columns); set_size(new_columns, rows());
set_size(new_columns, rows()); clear();
clear(); break;
break;
}
case 12:
if (should_set) {
// Start blinking cursor
m_cursor_style = steady_cursor_to_blinking(m_cursor_style);
} else {
// Stop blinking cursor
m_cursor_style = blinking_cursor_to_steady(m_cursor_style);
}
m_client.set_cursor_style(m_cursor_style);
break;
case 25:
if (should_set) {
// Show cursor
m_cursor_style = m_saved_cursor_style;
m_client.set_cursor_style(m_cursor_style);
} else {
// Hide cursor
m_saved_cursor_style = m_cursor_style;
m_cursor_style = None;
m_client.set_cursor_style(None);
}
break;
case 1047:
#ifndef KERNEL
if (should_set) {
dbgln_if(TERMINAL_DEBUG, "Switching to Alternate Screen Buffer");
m_use_alternate_screen_buffer = true;
clear();
} else {
dbgln_if(TERMINAL_DEBUG, "Switching to Normal Screen Buffer");
m_use_alternate_screen_buffer = false;
}
m_need_full_flush = true;
#else
dbgln("Alternate Screen Buffer is not supported");
#endif
break;
case 1048:
if (should_set)
SCOSC();
else
SCORC();
break;
case 1049:
#ifndef KERNEL
if (should_set) {
dbgln_if(TERMINAL_DEBUG, "Switching to Alternate Screen Buffer and saving state");
m_normal_saved_state = m_current_state;
m_use_alternate_screen_buffer = true;
clear();
} else {
dbgln_if(TERMINAL_DEBUG, "Switching to Normal Screen Buffer and restoring state");
m_current_state = m_normal_saved_state;
m_use_alternate_screen_buffer = false;
set_cursor(cursor_row(), cursor_column());
}
m_need_full_flush = true;
#else
dbgln("Alternate Screen Buffer is not supported");
#endif
break;
case 2004:
dbgln_if(TERMINAL_DEBUG, "Setting bracketed mode enabled={}", should_set);
m_needs_bracketed_paste = should_set;
break;
default:
dbgln("Terminal::alter_mode: Unimplemented private mode {} (should_set={})", mode, should_set);
break;
}
} }
} else { case 12:
for (auto mode : params) { if (should_set) {
switch (mode) { // Start blinking cursor
// FIXME: implement *something* for this m_cursor_style = steady_cursor_to_blinking(m_cursor_style);
default: } else {
dbgln("Terminal::alter_mode: Unimplemented mode {} (should_set={})", mode, should_set); // Stop blinking cursor
break; m_cursor_style = blinking_cursor_to_steady(m_cursor_style);
} }
m_client.set_cursor_style(m_cursor_style);
break;
case 25:
if (should_set) {
// Show cursor
m_cursor_style = m_saved_cursor_style;
m_client.set_cursor_style(m_cursor_style);
} else {
// Hide cursor
m_saved_cursor_style = m_cursor_style;
m_cursor_style = None;
m_client.set_cursor_style(None);
}
break;
case 1047:
#ifndef KERNEL
if (should_set) {
dbgln_if(TERMINAL_DEBUG, "Switching to Alternate Screen Buffer");
m_use_alternate_screen_buffer = true;
clear();
} else {
dbgln_if(TERMINAL_DEBUG, "Switching to Normal Screen Buffer");
m_use_alternate_screen_buffer = false;
}
m_need_full_flush = true;
#else
dbgln("Alternate Screen Buffer is not supported");
#endif
break;
case 1048:
if (should_set)
SCOSC();
else
SCORC();
break;
case 1049:
#ifndef KERNEL
if (should_set) {
dbgln_if(TERMINAL_DEBUG, "Switching to Alternate Screen Buffer and saving state");
m_normal_saved_state = m_current_state;
m_use_alternate_screen_buffer = true;
clear();
} else {
dbgln_if(TERMINAL_DEBUG, "Switching to Normal Screen Buffer and restoring state");
m_current_state = m_normal_saved_state;
m_use_alternate_screen_buffer = false;
set_cursor(cursor_row(), cursor_column());
}
m_need_full_flush = true;
#else
dbgln("Alternate Screen Buffer is not supported");
#endif
break;
case 2004:
dbgln_if(TERMINAL_DEBUG, "Setting bracketed mode enabled={}", should_set);
m_needs_bracketed_paste = should_set;
break;
default:
dbgln("Terminal::alter_private_mode: Unimplemented private mode {} (should_set={})", mode, should_set);
break;
} }
} }
} }
void Terminal::RM(Parameters params, Intermediates intermediates) void Terminal::RM(Parameters params)
{ {
alter_mode(false, params, intermediates); alter_ansi_mode(false, params);
} }
void Terminal::SM(Parameters params, Intermediates intermediates) void Terminal::DECRST(Parameters params)
{ {
alter_mode(true, params, intermediates); alter_private_mode(false, params);
}
void Terminal::SM(Parameters params)
{
alter_ansi_mode(true, params);
}
void Terminal::DECSET(Parameters params)
{
alter_private_mode(true, params);
} }
void Terminal::SGR(Parameters params) void Terminal::SGR(Parameters params)
@ -1085,124 +1096,95 @@ void Terminal::execute_csi_sequence(Parameters parameters, Intermediates interme
if (ignore) if (ignore)
dbgln("CSI sequence has its ignore flag set."); dbgln("CSI sequence has its ignore flag set.");
switch (last_byte) { if (intermediates.is_empty()) {
case '@': switch (last_byte) {
ICH(parameters); case '@':
break; return ICH(parameters);
case 'A': case 'A':
CUU(parameters); return CUU(parameters);
break; case 'B':
case 'B': return CUD(parameters);
CUD(parameters); case 'C':
break; return CUF(parameters);
case 'C': case 'D':
CUF(parameters); return CUB(parameters);
break; case 'E':
case 'D': return CNL(parameters);
CUB(parameters); case 'F':
break; return CPL(parameters);
case 'E': case 'G':
CNL(parameters); return CHA(parameters);
break; case 'H':
case 'F': return CUP(parameters);
CPL(parameters); case 'J':
break; return ED(parameters);
case 'G': case 'K':
CHA(parameters); return EL(parameters);
break; case 'L':
case 'H': return IL(parameters);
CUP(parameters); case 'M':
break; return DL(parameters);
case 'J': case 'P':
ED(parameters); return DCH(parameters);
break; case 'S':
case 'K': return SU(parameters);
EL(parameters); case 'T':
break; return SD(parameters);
case 'L': case 'X':
IL(parameters); return ECH(parameters);
break; case '`':
case 'M': return HPA(parameters);
DL(parameters); case 'a':
break; return HPR(parameters);
case 'P': case 'b':
DCH(parameters); return REP(parameters);
break; case 'c':
case 'S': return DA(parameters);
SU(parameters); case 'd':
break; return VPA(parameters);
case 'T': case 'e':
SD(parameters); return VPR(parameters);
break; case 'f':
case 'X': return HVP(parameters);
ECH(parameters); case 'h':
break; return SM(parameters);
case '`': case 'l':
HPA(parameters); return RM(parameters);
break; case 'm':
case 'a': return SGR(parameters);
HPR(parameters); case 'n':
break; return DSR(parameters);
case 'b': case 'r':
REP(parameters); return DECSTBM(parameters);
break; case 's':
case 'c': return SCOSC();
DA(parameters); case 't':
break; return XTERM_WM(parameters);
case 'd': case 'u':
VPA(parameters); return SCORC();
break; }
case 'e': } else if (intermediates.size() == 1 && intermediates[0] == '?') {
VPR(parameters); switch (last_byte) {
break; case 'h':
case 'f': return DECSET(parameters);
HVP(parameters); case 'l':
break; return DECRST(parameters);
case 'h': }
SM(parameters, intermediates); } else if (intermediates.size() == 1 && intermediates[0] == '\'') {
break; switch (last_byte) {
case 'l': case '}':
RM(parameters, intermediates); return DECIC(parameters);
break; case '~':
case 'm': return DECDC(parameters);
SGR(parameters); }
break; } else if (intermediates.size() == 1 && intermediates[0] == ' ') {
case 'n': switch (last_byte) {
DSR(parameters); case 'q':
break; return DECSCUSR(parameters);
case 'q': }
if (intermediates.size() >= 1 && intermediates[0] == ' ')
DECSCUSR(parameters);
else
unimplemented_csi_sequence(parameters, intermediates, last_byte);
break;
case 'r':
DECSTBM(parameters);
break;
case 's':
SCOSC();
break;
case 't':
XTERM_WM(parameters);
break;
case 'u':
SCORC();
break;
case '}':
if (intermediates.size() >= 1 && intermediates[0] == '\'')
DECIC(parameters);
else
unimplemented_csi_sequence(parameters, intermediates, last_byte);
break;
case '~':
if (intermediates.size() >= 1 && intermediates[0] == '\'')
DECDC(parameters);
else
unimplemented_csi_sequence(parameters, intermediates, last_byte);
break;
default:
unimplemented_csi_sequence(parameters, intermediates, last_byte);
} }
unimplemented_csi_sequence(parameters, intermediates, last_byte);
} }
void Terminal::execute_osc_sequence(OscParameters parameters, u8 last_byte) void Terminal::execute_osc_sequence(OscParameters parameters, u8 last_byte)
@ -1603,5 +1585,4 @@ Attribute Terminal::attribute_at(const Position& position) const
return line.attribute_at(position.column()); return line.attribute_at(position.column());
} }
#endif #endif
} }

View file

@ -226,7 +226,8 @@ protected:
void emit_string(const StringView&); void emit_string(const StringView&);
void alter_mode(bool should_set, Parameters, Intermediates); void alter_ansi_mode(bool should_set, Parameters);
void alter_private_mode(bool should_set, Parameters);
// CUU Cursor Up // CUU Cursor Up
void CUU(Parameters); void CUU(Parameters);
@ -274,10 +275,16 @@ protected:
void DECSTBM(Parameters); void DECSTBM(Parameters);
// RM Reset Mode // RM Reset Mode
void RM(Parameters, Intermediates); void RM(Parameters);
// DECRST - DEC Private Mode Reset
void DECRST(Parameters);
// SM Set Mode // SM Set Mode
void SM(Parameters, Intermediates); void SM(Parameters);
// DECSET - Dec Private Mode Set
void DECSET(Parameters);
// DA - Device Attributes // DA - Device Attributes
void DA(Parameters); void DA(Parameters);