mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 21:27:34 +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:
parent
52aa777d49
commit
0e04f7cf1e
2 changed files with 201 additions and 213 deletions
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue