From 02e00944f6e0c751be3ed453696518008d99de53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Mon, 30 Jan 2017 17:27:17 +0100 Subject: [PATCH] Fix possible range violation in BatchBuffer.popFront(N). --- source/vibe/internal/array.d | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/vibe/internal/array.d b/source/vibe/internal/array.d index 354816b..d630c2c 100644 --- a/source/vibe/internal/array.d +++ b/source/vibe/internal/array.d @@ -570,12 +570,17 @@ struct BatchBuffer(T, size_t N = 0) { @property void capacity(size_t n) { assert(n >= m_fill); m_buffer.length = n; } } - @property bool empty() const { return m_first >= m_fill; } + @property bool empty() const { assert(m_first < m_fill || m_fill == 0 && m_first == 0); return m_first >= m_fill; } @property size_t capacity() const { return m_buffer.length; } @property size_t length() const { return m_fill - m_first; } @property ref inout(T) front() inout { assert(!empty); return m_buffer[m_first]; } - void popFront() { assert(!empty); m_first++; } - void popFrontN(size_t n) { assert(n <= length); m_first += n; } + void popFront() { popFrontN(1); } + void popFrontN(size_t n) { + assert(n <= length); + m_first += n; + if (m_first == m_fill) + m_first = m_fill = 0; + } inout(T)[] peek() inout { return m_buffer[m_first .. m_fill]; } T[] peekDst() { assert(empty); return m_buffer; } void putN(size_t n) { assert(empty && n <= m_buffer.length); m_fill = n; } @@ -583,9 +588,7 @@ struct BatchBuffer(T, size_t N = 0) { void read(T[] dst) { assert(length() >= dst.length); dst[] = m_buffer[m_first .. m_first + dst.length]; - m_first += dst.length; - assert(m_first <= m_fill); - if (m_first == m_fill) m_first = m_fill = 0; + popFrontN(dst.length); } }