@ 261102.1

261008.3 · 33a3456921a17c53f42f8610783b6d379d652d3e

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.

reading declarations

Changes to src/tui/. All files

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} 			}

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())+	}+}