From 523ac9f35e45e244da37c53452a4901d13291a49 Mon Sep 17 00:00:00 2001 From: TowyTowy <85077986+TowyTowy@users.noreply.github.com> Date: Wed, 15 Jul 2026 22:04:37 +0200 Subject: [PATCH] fix(utils): prevent panic when pushing to a zero-size ring buffer (#4840) Co-authored-by: Claude --- internal/utils/ring_buffer.go | 5 +++++ internal/utils/ring_buffer_test.go | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/internal/utils/ring_buffer.go b/internal/utils/ring_buffer.go index 1bf609f7..0d05ba81 100644 --- a/internal/utils/ring_buffer.go +++ b/internal/utils/ring_buffer.go @@ -37,6 +37,11 @@ func RingBufferFrom[T any](size int, data []T) *RingBuffer[T] { func (r *RingBuffer[T]) Push(data T) { r.mutex.Lock() defer r.mutex.Unlock() + if r.Size <= 0 { + // A zero (or negative) capacity buffer holds nothing. Bail out before + // indexing r.data or taking a modulo by r.Size, both of which panic. + return + } if len(r.data) == r.Size { r.data[r.start] = data r.start = (r.start + 1) % r.Size diff --git a/internal/utils/ring_buffer_test.go b/internal/utils/ring_buffer_test.go index cc10b691..39df2f36 100644 --- a/internal/utils/ring_buffer_test.go +++ b/internal/utils/ring_buffer_test.go @@ -44,6 +44,24 @@ func TestRingBuffer_MarshalJSON(t *testing.T) { } } +func TestRingBuffer_ZeroSize(t *testing.T) { + // A zero-capacity buffer must hold nothing rather than panic. This is + // reachable from the logs endpoint (?min=0), which builds NewRingBuffer(0). + rb := NewRingBuffer[int](0) + + rb.Push(1) + rb.Push(2) + + if rb.Len() != 0 { + t.Errorf("Expected len to be 0, got %d", rb.Len()) + } + + data := rb.Data() + if len(data) != 0 { + t.Errorf("Expected data to be empty, got %v", data) + } +} + func TestRingBuffer_Clear(t *testing.T) { rb := NewRingBuffer[int](3)