golang/go · error

bytes: Repeat output length overflow

Error message

bytes: Repeat output length overflow

What it means

bytes.Repeat computes the output length via a full 128-bit multiplication: hi, lo := bits.Mul(uint(len(b)), uint(count)). It panics with "bytes: Repeat output length overflow" when hi > 0 (the product exceeds 64 bits) OR lo > uint(maxInt) (the product exceeds the addressable int range). This catches both true 64-bit overflow and the platform-specific maxInt ceiling; it is the guard that the count<0 check cannot cover.

Source

Thrown at src/bytes/bytes.go:643

// Repeat returns a new byte slice consisting of count copies of b.
//
// It panics if count is negative or if the result of (len(b) * count)
// overflows.
func Repeat(b []byte, count int) []byte {
	if count == 0 {
		return []byte{}
	}

	// Since we cannot return an error on overflow,
	// we should panic if the repeat will generate an overflow.
	// See golang.org/issue/16237.
	if count < 0 {
		panic("bytes: negative Repeat count")
	}
	hi, lo := bits.Mul(uint(len(b)), uint(count))
	if hi > 0 || lo > uint(maxInt) {
		panic("bytes: Repeat output length overflow")
	}
	n := int(lo) // lo = len(b) * count

	if len(b) == 0 {
		return []byte{}
	}

	// Past a certain chunk size it is counterproductive to use
	// larger chunks as the source of the write, as when the source
	// is too large we are basically just thrashing the CPU D-cache.
	// So if the result length is larger than an empirically-found
	// limit (8KB), we stop growing the source string once the limit
	// is reached and keep reusing the same source string - that
	// should therefore be always resident in the L1 cache - until we
	// have completed the construction of the result.
	// This yields significant speedups (up to +100%) in cases where
	// the result length is large (roughly, over L2 cache size).
	const chunkLimit = 8 * 1024

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Cap the desired output length and derive count from it: if len(b) == 0 handle separately, else count = min(desiredLen/len(b), maxCount) with an explicit upper bound.
  2. Before calling Repeat, check the product fits: if uint(len(b)) > maxInt/uint(count) (with count>0), reject or reduce.
  3. For huge outputs, write repetitions to an io.Writer in a loop rather than materializing one slice.

Example fix

// before
out := bytes.Repeat(pattern, count) // len(pattern)*count may overflow

// after
if len(pattern) == 0 {
    out = []byte{}
} else if count < 0 {
    panic("negative count")
} else if uint(len(pattern)) > uint(maxInt)/uint(count) {
    return fmt.Errorf("repeat output too large")
} else {
    out = bytes.Repeat(pattern, count)
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard the len(b)*count multiplication before Repeat.
func safeRepeatLen(b []byte, count int) ([]byte, error) {
    if count < 0 {
        return nil, fmt.Errorf("negative repeat count")
    }
    if len(b) == 0 {
        return []byte{}, nil
    }
    if uint(len(b)) > uint(maxInt)/uint(count) {
        return nil, fmt.Errorf("repeat output length overflow")
    }
    return bytes.Repeat(b, count), nil
}

Prevention

When it happens

Trigger: Calling bytes.Repeat(b, count) where len(b)*count overflows: large input slice with a large count, or a moderately sized pattern repeated to fill a huge target; computing count from a desired output length without checking that len(b)*count fits; attacker-controlled count paired with a non-trivial pattern.

Common situations: Generating alignment/padding from a pattern to a target size expressed in bytes; replicating a template block a computed number of times; building a repeating key/keystream of a requested length; fuzz/test inputs that scale count to extreme values.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/62740e223a2651bc. Report an issue: GitHub.