fix escape code leak
This commit is contained in:
+66
-16
@@ -482,7 +482,9 @@ impl SharedParser {
|
||||
|
||||
// Like Kitty line 1516: consume_input(self, ...)
|
||||
let made_progress = self.consume_input(handler);
|
||||
parsed_any = true;
|
||||
if made_progress {
|
||||
parsed_any = true;
|
||||
}
|
||||
|
||||
// Re-acquire lock
|
||||
state = self.state.lock().unwrap();
|
||||
@@ -635,14 +637,14 @@ impl SharedParser {
|
||||
true
|
||||
}
|
||||
State::Csi => {
|
||||
// Like Kitty lines 1465-1466:
|
||||
// if (consume_csi(self)) { self->read.consumed = self->read.pos; if (self->csi.is_valid) dispatch_csi(self); SET_STATE(NORMAL); }
|
||||
let state_before = *vte_state;
|
||||
if Self::consume_csi_impl(
|
||||
handler,
|
||||
buf,
|
||||
parse_pos,
|
||||
parse_sz,
|
||||
*parse_consumed,
|
||||
parse_consumed,
|
||||
vte_state,
|
||||
csi,
|
||||
escape_len,
|
||||
) {
|
||||
@@ -650,30 +652,41 @@ impl SharedParser {
|
||||
if csi.is_valid {
|
||||
handler.csi(csi);
|
||||
}
|
||||
*vte_state = State::Normal;
|
||||
if *vte_state == state_before {
|
||||
*vte_state = State::Normal;
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
*vte_state != state_before
|
||||
}
|
||||
}
|
||||
State::Osc => {
|
||||
let state_before = *vte_state;
|
||||
if Self::consume_osc_impl(
|
||||
handler, buf, parse_pos, parse_sz, vte_state, osc_buffer,
|
||||
handler,
|
||||
buf,
|
||||
parse_pos,
|
||||
parse_sz,
|
||||
parse_consumed,
|
||||
vte_state,
|
||||
osc_buffer,
|
||||
escape_len,
|
||||
) {
|
||||
*parse_consumed = *parse_pos;
|
||||
*vte_state = State::Normal;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
*vte_state != state_before
|
||||
}
|
||||
}
|
||||
State::Dcs | State::Apc | State::Pm | State::Sos => {
|
||||
let state_before = *vte_state;
|
||||
if Self::consume_string_impl(
|
||||
handler,
|
||||
buf,
|
||||
parse_pos,
|
||||
parse_sz,
|
||||
parse_consumed,
|
||||
vte_state,
|
||||
string_buffer,
|
||||
escape_len,
|
||||
@@ -682,7 +695,7 @@ impl SharedParser {
|
||||
*vte_state = State::Normal;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
*vte_state != state_before
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -837,6 +850,11 @@ impl SharedParser {
|
||||
b'\\' => {
|
||||
*vte_state = State::Normal;
|
||||
}
|
||||
0x1B => {
|
||||
// ESC followed by ESC. Start new escape sequence.
|
||||
*vte_state = State::Escape;
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
log::debug!("Unknown escape sequence: ESC {:02x}", ch);
|
||||
*vte_state = State::Normal;
|
||||
@@ -913,7 +931,8 @@ impl SharedParser {
|
||||
buf: &[u8; BUF_SIZE],
|
||||
parse_pos: &mut usize,
|
||||
parse_sz: usize,
|
||||
parse_consumed: usize,
|
||||
parse_consumed: &mut usize,
|
||||
vte_state: &mut State,
|
||||
csi: &mut CsiParams,
|
||||
escape_len: &mut usize,
|
||||
) -> bool {
|
||||
@@ -922,8 +941,15 @@ impl SharedParser {
|
||||
*parse_pos += 1;
|
||||
*escape_len += 1;
|
||||
|
||||
if ch == 0x1B {
|
||||
*vte_state = State::Escape;
|
||||
*parse_consumed = *parse_pos;
|
||||
*escape_len = 0;
|
||||
return false; // Aborted by new ESC
|
||||
}
|
||||
|
||||
// Handle embedded control characters
|
||||
if ch <= 0x1F && ch != 0x1B {
|
||||
if ch <= 0x1F {
|
||||
handler.control(ch);
|
||||
continue;
|
||||
}
|
||||
@@ -1023,7 +1049,7 @@ impl SharedParser {
|
||||
}
|
||||
|
||||
// Check max length
|
||||
if *parse_pos - parse_consumed > MAX_ESCAPE_LEN {
|
||||
if *parse_pos - *parse_consumed > MAX_ESCAPE_LEN {
|
||||
log::debug!("CSI escape too long, ignoring");
|
||||
return true;
|
||||
}
|
||||
@@ -1037,6 +1063,7 @@ impl SharedParser {
|
||||
buf: &[u8; BUF_SIZE],
|
||||
parse_pos: &mut usize,
|
||||
parse_sz: usize,
|
||||
parse_consumed: &mut usize,
|
||||
vte_state: &mut State,
|
||||
osc_buffer: &mut Vec<u8>,
|
||||
escape_len: &mut usize,
|
||||
@@ -1069,6 +1096,7 @@ impl SharedParser {
|
||||
*parse_pos += 1;
|
||||
handler.osc(osc_buffer);
|
||||
*vte_state = State::Escape;
|
||||
*parse_consumed = *parse_pos;
|
||||
*escape_len = 0;
|
||||
return false;
|
||||
} else {
|
||||
@@ -1098,6 +1126,7 @@ impl SharedParser {
|
||||
buf: &[u8; BUF_SIZE],
|
||||
parse_pos: &mut usize,
|
||||
parse_sz: usize,
|
||||
parse_consumed: &mut usize,
|
||||
vte_state: &mut State,
|
||||
string_buffer: &mut Vec<u8>,
|
||||
escape_len: &mut usize,
|
||||
@@ -1128,10 +1157,17 @@ impl SharedParser {
|
||||
);
|
||||
return true;
|
||||
} else if *parse_pos + 1 < parse_sz {
|
||||
// ESC not followed by \ - include in buffer
|
||||
string_buffer.push(ch);
|
||||
// ESC not followed by \ - abort string, start new escape
|
||||
*parse_pos += 1;
|
||||
*escape_len += 1;
|
||||
Self::dispatch_string_command(
|
||||
handler,
|
||||
vte_state,
|
||||
string_buffer,
|
||||
);
|
||||
*vte_state = State::Escape;
|
||||
*parse_consumed = *parse_pos;
|
||||
*escape_len = 0;
|
||||
return false;
|
||||
} else {
|
||||
// ESC at end of buffer - need more data
|
||||
return false;
|
||||
@@ -1368,6 +1404,11 @@ impl Parser {
|
||||
self.state = State::Normal;
|
||||
1
|
||||
}
|
||||
0x1B => {
|
||||
// ESC followed by ESC. Start new escape sequence.
|
||||
self.state = State::Escape;
|
||||
1
|
||||
}
|
||||
_ => {
|
||||
// Unknown escape sequence, ignore and return to normal
|
||||
log::debug!("Unknown escape sequence: ESC {:02x}", ch);
|
||||
@@ -1442,8 +1483,17 @@ impl Parser {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
if ch == 0x1B {
|
||||
self.state = State::Escape;
|
||||
self.escape_len = 0;
|
||||
// Wait! If it's ESC, we consumed it. But the next loop in parse() will call consume_escape,
|
||||
// which EXPECTS the char AFTER ESC.
|
||||
// So consuming it is PERFECT!
|
||||
return consumed;
|
||||
}
|
||||
|
||||
// Handle control characters embedded in CSI (common to all states)
|
||||
if ch <= 0x1F && ch != 0x1B {
|
||||
if ch <= 0x1F {
|
||||
handler.control(ch);
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user