From 91e7690beea25a9860afd627cc094bffd685e335 Mon Sep 17 00:00:00 2001 From: gammazero <11790789+gammazero@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:41:42 -1000 Subject: [PATCH] fix panic if copying in exactly the buffer size If Copy or CopyInSlice copied exactly the buffer size nubber of elements, and then an item was removed from the back of the deque, this caused a panic. This was due to the tail not being wrapped around to the front of the buffer if the data copied in aligned with the buffer boundary. This is fixed by properly wrapping the tail index to the start of the buffer. Closes #47 --- deque.go | 4 ++-- deque_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/deque.go b/deque.go index 6751821..70b46eb 100644 --- a/deque.go +++ b/deque.go @@ -320,7 +320,7 @@ func (q *Deque[T]) Copy(src Deque[T]) int { q.Grow(src.Len()) n := src.CopyOutSlice(q.buf) q.count = n - q.tail = n + q.tail = n & (len(q.buf) - 1) // bitwise modulus q.head = 0 return n } @@ -380,7 +380,7 @@ func (q *Deque[T]) CopyInSlice(in []T) { } n := copy(q.buf, in) q.count = n - q.tail = n + q.tail = n & (len(q.buf) - 1) // bitwise modulus q.head = 0 } diff --git a/deque_test.go b/deque_test.go index 9c730ec..0bda943 100644 --- a/deque_test.go +++ b/deque_test.go @@ -1275,6 +1275,34 @@ func TestCopy(t *testing.T) { } } +func TestClearAndPushBack(t *testing.T) { + q := &Deque[int]{} + in := make([]int, minCapacity) + q.Clear() + for i := range in { + q.PushBack(in[i]) + } + q.PopFront() + q.PushBack(17) +} + +func TestCopyPanic(t *testing.T) { + var q1, q2 Deque[int] + in := make([]int, minCapacity) + q1.CopyInSlice(in) + q2.Copy(q1) + q2.PopFront() + q2.PushBack(17) +} + +func TestCopyInSlicePanic(t *testing.T) { + var q Deque[int] + in := make([]int, minCapacity) + q.CopyInSlice(in) + q.PopFront() + q.PushBack(17) +} + func assertPanics(t *testing.T, name string, f func()) { defer func() { if r := recover(); r == nil {