From b8337eda6b501f92a75ec1c3bcfb755c89596250 Mon Sep 17 00:00:00 2001 From: semihbkgr Date: Mon, 26 Jan 2026 01:13:41 +0300 Subject: [PATCH] fix(viewport): prevent panic when height is negative or zero When viewport height becomes negative (e.g., during terminal resize), visibleLines() could panic with "slice bounds out of range" because bottom becomes less than top in the slice operation. Add a guard to return nil when top >= bottom to prevent the panic. Fixes #879 Co-Authored-By: Claude Opus 4.5 --- viewport/viewport.go | 3 +++ viewport/viewport_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/viewport/viewport.go b/viewport/viewport.go index 5862ac05e..3dedd1d25 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -147,6 +147,9 @@ func (m Model) visibleLines() (lines []string) { if len(m.lines) > 0 { top := max(0, m.YOffset) bottom := clamp(m.YOffset+h, top, len(m.lines)) + if top >= bottom { + return nil + } lines = m.lines[top:bottom] } diff --git a/viewport/viewport_test.go b/viewport/viewport_test.go index 6f8cb371b..02b89ad1b 100644 --- a/viewport/viewport_test.go +++ b/viewport/viewport_test.go @@ -201,6 +201,38 @@ func TestVisibleLines(t *testing.T) { } }) + t.Run("negative height should not panic", func(t *testing.T) { + t.Parallel() + + m := New(10, 10) + m.SetContent(strings.Join(defaultList, "\n")) + m.YOffset = 5 + m.Height = -4 + + // This should not panic + list := m.visibleLines() + + if list != nil { + t.Errorf("list should be nil with negative height, got %d items", len(list)) + } + }) + + t.Run("zero height should not panic", func(t *testing.T) { + t.Parallel() + + m := New(10, 10) + m.SetContent(strings.Join(defaultList, "\n")) + m.YOffset = 5 + m.Height = 0 + + // This should not panic + list := m.visibleLines() + + if list != nil { + t.Errorf("list should be nil with zero height, got %d items", len(list)) + } + }) + t.Run("empty list: with indent", func(t *testing.T) { t.Parallel()