From 33a3456921a17c53f42f8610783b6d379d652d3e Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Thu, 8 Oct 2026 21:42:32 +0900 Subject: [PATCH] Fix panic on a read error during the second-chance read The read error left a nil buffer, and the deferred slice in GetChar panicked instead of returning Fatal. --- src/tui/light.go | 4 +++- src/tui/light_query_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/tui/light.go b/src/tui/light.go index 4616dad0..b8c6ac7a 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -593,10 +593,12 @@ func (r *LightRenderer) GetChar(cancellable bool) Event { // follows in the buffer. if ev.Type == Invalid && stillArriving(r.buffer) { waited := len(r.buffer) - r.buffer, result, err = r.getBytes(true) + var buffer []byte + buffer, result, err = r.getBytes(true) if err != nil { return Event{Fatal, 0, nil} } + r.buffer = buffer if result == getCharCancelled { return Event{Invalid, 0, nil} } diff --git a/src/tui/light_query_test.go b/src/tui/light_query_test.go index 28704c57..a5ab1f48 100644 --- a/src/tui/light_query_test.go +++ b/src/tui/light_query_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" "time" + + "golang.org/x/term" ) // Drives queryStartup against a terminal simulated by pipes, with the replies @@ -155,3 +157,26 @@ func TestLateKeyAfterUnfinishedSequence(t *testing.T) { } t.Error("the late key was dropped") } + +// A read error during the second-chance read must end fzf cleanly, not panic. +func TestSecondChanceReadError(t *testing.T) { + inR, inW, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { inR.Close() }) + inW.WriteString("\x1b[12") + go func() { + time.Sleep(2 * defaultEscDelay * time.Millisecond) + inW.Close() + }() + + out, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0) + if err != nil { + t.Fatal(err) + } + r := &LightRenderer{ttyin: inR, ttyout: out, escDelay: defaultEscDelay, origState: &term.State{}} + if ev := r.GetChar(false); ev.Type != Fatal { + t.Errorf("got %s, want Fatal", ev.Type.String()) + } +}