mirror of
https://github.com/junegunn/fzf.git
synced 2026-09-28 22:52:27 +08:00
Wait for a string terminator split across reads
A trailing ESC was read as a lone ESC, so the read loop stopped waiting and the parser was handed an unterminated sequence, whose payload was typed into the query. With ESCDELAY=0 nothing covered it. Reported by Copilot on #4926.
This commit is contained in:
@@ -414,6 +414,14 @@ func incompleteEscape(buffer []byte) bool {
|
||||
tail = tail[len(tail)-escapeLookback:]
|
||||
}
|
||||
start := bytes.LastIndexByte(tail, Esc.Byte())
|
||||
// A trailing ESC can be the first half of a string terminator. Reading it as
|
||||
// a lone ESC ends the wait and hands the parser an unterminated sequence, so
|
||||
// fall back to the one this ESC would have terminated.
|
||||
if start == len(tail)-1 && start > 0 {
|
||||
if prev := bytes.LastIndexByte(tail[:start], Esc.Byte()); prev >= 0 {
|
||||
start = prev
|
||||
}
|
||||
}
|
||||
if start < 0 || len(tail)-start < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -65,6 +65,18 @@ func TestIncompleteStringEscape(t *testing.T) {
|
||||
{"\x1b]0;title\x1b\\", false},
|
||||
{"\x1bP>|kitty(0.48.2)\x1b\\", false},
|
||||
{"ab\x1b]11;rgb:", true},
|
||||
|
||||
// A string terminator split across reads: the ESC has arrived, the
|
||||
// backslash has not
|
||||
{"\x1b]0;t\x1b", true},
|
||||
{"\x1bP>|kitty\x1b", true},
|
||||
{"\x1b_G\x1b", true},
|
||||
|
||||
// Complete sequence followed by a lone ESC, which is the ESC key
|
||||
{"\x1b]0;title\a\x1b", false},
|
||||
{"\x1b\x1b", false},
|
||||
{"\x1ba\x1b", false},
|
||||
{"\x1b[A\x1b", false},
|
||||
} {
|
||||
if got := incompleteEscape([]byte(c.buffer)); got != c.want {
|
||||
t.Errorf("incompleteEscape(%q) = %v, want %v", c.buffer, got, c.want)
|
||||
|
||||
Reference in New Issue
Block a user