From f3cdcad5416b36d10460a45804411a93c88b3c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E6=89=87=E6=BB=91=E7=BF=94=E7=BF=BC?= Date: Fri, 15 Aug 2025 23:27:12 +0800 Subject: [PATCH] common/buf/multi_buffer.go: Fix Compact() (#5015) Fixes https://github.com/XTLS/Xray-core/issues/5012 Co-authored-by: patterniha <71074308+patterniha@users.noreply.github.com> --- common/buf/buffer.go | 8 ++++++++ common/buf/multi_buffer.go | 2 +- common/buf/multi_buffer_test.go | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/common/buf/buffer.go b/common/buf/buffer.go index 2aa60e6a..04c886a7 100644 --- a/common/buf/buffer.go +++ b/common/buf/buffer.go @@ -244,6 +244,14 @@ func (b *Buffer) Cap() int32 { return int32(len(b.v)) } +// Available returns the available capacity of the buffer content. +func (b *Buffer) Available() int32 { + if b == nil { + return 0 + } + return int32(len(b.v)) - b.end +} + // IsEmpty returns true if the buffer is empty. func (b *Buffer) IsEmpty() bool { return b.Len() == 0 diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go index f3b17aef..fcac84d7 100644 --- a/common/buf/multi_buffer.go +++ b/common/buf/multi_buffer.go @@ -144,7 +144,7 @@ func Compact(mb MultiBuffer) MultiBuffer { for i := 1; i < len(mb); i++ { curr := mb[i] - if last.Len()+curr.Len() > Size { + if curr.Len() > last.Available() { mb2 = append(mb2, last) last = curr } else { diff --git a/common/buf/multi_buffer_test.go b/common/buf/multi_buffer_test.go index 2b83a548..40dbdd63 100644 --- a/common/buf/multi_buffer_test.go +++ b/common/buf/multi_buffer_test.go @@ -175,6 +175,29 @@ func TestCompact(t *testing.T) { } } +func TestCompactWithConsumed(t *testing.T) { + // make a consumed buffer (a.Start != 0) + a := New() + for range 8192 { + common.Must2(a.WriteString("a")) + } + a.Read(make([]byte, 2)) + + b := New() + for range 2 { + common.Must2(b.WriteString("b")) + } + + mb := MultiBuffer{a, b} + cmb := Compact(mb) + mbc := &MultiBufferContainer{mb} + mbc.Read(make([]byte, 8190)) + + if w := cmb.String(); w != "bb" { + t.Error("unexpected Compact result ", w) + } +} + func BenchmarkSplitBytes(b *testing.B) { var mb MultiBuffer raw := make([]byte, Size)