pion/webrtc · error

%w: unreasonable comment count

Error message

%w: unreasonable comment count

What it means

This error is returned by parseUserComments (called from ParseOpusTags) when the OpusTags header declares a user comment count that cannot possibly fit in the remaining payload. The count is a little-endian uint32 read from the payload; if count > (len(payload)-vendorEnd)/u32Size, there are not even enough bytes for per-comment length fields, so the header is corrupt or malicious.

Source

Thrown at pkg/media/oggreader/oggreader.go:445

		return "", 0, fmt.Errorf("%w: payload too short for vendor string", errBadOpusTagsSignature)
	}
	vendorLen := int(vendorLen32)

	vendorStart := headerMagicLen + u32Size
	vendorEnd := vendorStart + vendorLen
	if vendorEnd+u32Size > len(payload) {
		return "", 0, fmt.Errorf("%w: payload too short for vendor+comment count", errBadOpusTagsSignature)
	}

	vendor := string(payload[vendorStart:vendorEnd])

	return vendor, vendorEnd, nil
}

func parseUserComments(payload []byte, vendorEnd, u32Size int) ([]UserComment, error) {
	userCommentCount32 := binary.LittleEndian.Uint32(payload[vendorEnd : vendorEnd+u32Size])
	if int(userCommentCount32) > (len(payload)-vendorEnd)/u32Size {
		return nil, fmt.Errorf("%w: unreasonable comment count", errBadOpusTagsSignature)
	}
	userCommentCount := int(userCommentCount32)

	pos := vendorEnd + u32Size
	userComments := make([]UserComment, userCommentCount)

	for i := range userComments {
		comment, nextPos, err := parseSingleUserComment(payload, pos, u32Size, i)
		if err != nil {
			return nil, err
		}
		userComments[i] = comment
		pos = nextPos
	}

	return userComments, nil
}

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Verify the input file is complete and uncorrupted (re-download or re-encode the source).
  2. Validate the OpusTags header structure before parsing: check the 'OpusTags' magic, vendor length, and comment count against the payload length.
  3. Use errors.Is(err, errBadOpusTagsSignature) to detect this class of malformed-header error and reject the file.
  4. If the input comes from untrusted sources, sanitize/re-encode metadata with a known-good tool (e.g. opustags, ffmpeg) before parsing.

Example fix

// before: parsing raw possibly-truncated payload
comments, err := ParseOpusTags(payload)
// after: pre-validate count field against payload size
if len(payload) < 8+4 { return errors.New("payload too short") }
count := binary.LittleEndian.Uint32(payload[len(payload)-4:])
if int(count) > (len(payload)-8-4)/4 { return errors.New("unreasonable comment count") }
comments, err := ParseOpusTags(payload)
Defensive patterns

Strategy: validation

Validate before calling

func hasReasonableCommentCount(payload []byte, vendorEnd, u32Size int) bool {
    if vendorEnd+u32Size > len(payload) { return false }
    count := int(binary.LittleEndian.Uint32(payload[vendorEnd : vendorEnd+u32Size]))
    return count <= (len(payload)-vendorEnd)/u32Size
}

Try / catch

comments, err := ParseOpusTags(payload)
if err != nil {
    if errors.Is(err, errBadOpusTagsSignature) {
        return fmt.Errorf("malformed OpusTags header: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ParseOpusTags on a payload whose 4-byte comment count field (after the vendor string) is larger than the number of remaining bytes divided by u32Size — i.e. a truncated, corrupted, or maliciously crafted OpusTags packet.

Common situations: Parsing truncated Ogg Opus files (incomplete downloads), hand-edited or corrupted metadata, fuzzed/malicious input claiming billions of comments, or feeding a non-OpusTags packet to ParseOpusTags.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/aad7e51e029fd2b6. Report an issue: GitHub.