From 67fdec4daa8fa3e6ffcafe3b18a76aa1ed22d614 Mon Sep 17 00:00:00 2001 From: waterme1on Date: Sun, 2 Aug 2026 05:37:06 +0700 Subject: [PATCH 1/2] fix: Import math and validate request body size Add math import and check for bulk request body size. fix protect all allocation-size arithmetic by checking for overflow before computing/using capacities. For this specific issue, make `Buf.grow` compute a target capacity without overflowing, and panic with a clear message if growth cannot be represented as `int`. Best targeted fix (no functional change beyond safety): - Edit `internal/pkg/danger/buf.go`, function `grow`. - Replace `2*cap(b.buf)+n` with guarded arithmetic: - Validate `n >= 0` (defensive, even though `Grow` checks). - Compute required capacity `need := len(b.buf) + n` with overflow check. - Compute doubled capacity from current cap with overflow check/saturation. - Choose `newCap = max(need, doubledCap)`. - Allocate with `make([]byte, len(b.buf), newCap)`. - Add `math` import for `math.MaxInt`. --- internal/pkg/bulk/opBulk.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/pkg/bulk/opBulk.go b/internal/pkg/bulk/opBulk.go index 437b743a15..49371e19f2 100644 --- a/internal/pkg/bulk/opBulk.go +++ b/internal/pkg/bulk/opBulk.go @@ -9,6 +9,7 @@ import ( "context" "errors" "fmt" + "math" "time" "github.com/elastic/go-elasticsearch/v8/esapi" @@ -59,6 +60,9 @@ func (b *Bulker) waitBulkAction(ctx context.Context, action actionT, index, id s // Serialize request const kSlop = 64 + if len(body) > math.MaxInt-kSlop { + return nil, fmt.Errorf("bulk request body too large") + } blk.buf.Grow(len(body) + kSlop) if err := b.writeBulkMeta(&blk.buf, action.String(), index, id, opt.RetryOnConflict); err != nil { From e4c961d72877e20d7429e96b8fcb8b0568d8964b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BJ=C3=B6rmungandrk?= Date: Sat, 1 Aug 2026 22:39:47 +0000 Subject: [PATCH 2/2] fix: Add math import and validate request body size --- internal/pkg/bulk/opMulti.go | 6 +++++- internal/pkg/danger/buf.go | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/internal/pkg/bulk/opMulti.go b/internal/pkg/bulk/opMulti.go index e6901b9e98..1f0945f740 100644 --- a/internal/pkg/bulk/opMulti.go +++ b/internal/pkg/bulk/opMulti.go @@ -60,7 +60,11 @@ func (b *Bulker) multiWaitBulkOp(ctx context.Context, action actionT, ops []Mult // O(n) Determine how much space we need var byteCnt int for _, op := range ops { - byteCnt += b.calcBulkSz(actionStr, op.Index, op.ID, opt.RetryOnConflict, op.Body) + sz := b.calcBulkSz(actionStr, op.Index, op.ID, opt.RetryOnConflict, op.Body) + if sz > math.MaxInt-byteCnt { + return nil, errors.New("bulk payload too large") + } + byteCnt += sz } // Create one bulk buffer to serialize each piece. diff --git a/internal/pkg/danger/buf.go b/internal/pkg/danger/buf.go index 8b7a4510d8..38d577ea19 100644 --- a/internal/pkg/danger/buf.go +++ b/internal/pkg/danger/buf.go @@ -9,6 +9,7 @@ package danger // Effectively golang's string builder with a Reset option import ( + "math" "unicode/utf8" ) @@ -33,7 +34,31 @@ func (b *Buf) Reset() { } func (b *Buf) grow(n int) { - buf := make([]byte, len(b.buf), 2*cap(b.buf)+n) + if n < 0 { + panic("danger.Buf.grow: negative count") + } + + l := len(b.buf) + c := cap(b.buf) + + if n > math.MaxInt-l { + panic("danger.Buf.grow: size overflow") + } + need := l + n + + var doubled int + if c > math.MaxInt/2 { + doubled = math.MaxInt + } else { + doubled = 2 * c + } + + newCap := need + if doubled > newCap { + newCap = doubled + } + + buf := make([]byte, l, newCap) copy(buf, b.buf) b.buf = buf } @@ -50,6 +75,9 @@ func (b *Buf) Grow(n int) { // Write appends the contents of p to b's buffer. // Write always returns len(p), nil. func (b *Buf) Write(p []byte) (int, error) { + if len(p) > 0 { + b.Grow(len(p)) + } b.buf = append(b.buf, p...) return len(p), nil } @@ -57,6 +85,7 @@ func (b *Buf) Write(p []byte) (int, error) { // WriteByte appends the byte c to b's buffer. // The returned error is always nil. func (b *Buf) WriteByte(c byte) error { + b.Grow(1) b.buf = append(b.buf, c) return nil } @@ -80,6 +109,9 @@ func (b *Buf) WriteRune(r rune) (int, error) { // WriteString appends the contents of s to b's buffer. // It returns the length of s and a nil error. func (b *Buf) WriteString(s string) (int, error) { + if len(s) > 0 { + b.Grow(len(s)) + } b.buf = append(b.buf, s...) return len(s), nil }