{"record":{"id":"8bb75e98e6a58469","repo":"pion/webrtc","slug":"w-payload-too-short-for-vendor-string","errorCode":null,"errorMessage":"%w: payload too short for vendor string","messagePattern":"%w: payload too short for vendor string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/media/oggreader/oggreader.go","lineNumber":427,"sourceCode":"}\n\nfunc validateOpusTagsHeader(payload []byte, minHeaderLen int) error {\n\tif len(payload) < minHeaderLen {\n\t\treturn fmt.Errorf(\"%w: payload too short\", errBadOpusTagsSignature)\n\t}\n\n\tgot := HeaderType(payload[:8])\n\tif got != HeaderOpusTags {\n\t\treturn fmt.Errorf(\"%w: expected %q, got %q\", errBadOpusTagsSignature, HeaderOpusTags, got)\n\t}\n\n\treturn nil\n}\n\nfunc parseVendorString(payload []byte, headerMagicLen, u32Size, minHeaderLen int) (string, int, error) {\n\tvendorLen32 := binary.LittleEndian.Uint32(payload[headerMagicLen : headerMagicLen+u32Size])\n\tif int(vendorLen32) > len(payload)-minHeaderLen {\n\t\treturn \"\", 0, fmt.Errorf(\"%w: payload too short for vendor string\", errBadOpusTagsSignature)\n\t}\n\tvendorLen := int(vendorLen32)\n\n\tvendorStart := headerMagicLen + u32Size\n\tvendorEnd := vendorStart + vendorLen\n\tif vendorEnd+u32Size > len(payload) {\n\t\treturn \"\", 0, fmt.Errorf(\"%w: payload too short for vendor+comment count\", errBadOpusTagsSignature)\n\t}\n\n\tvendor := string(payload[vendorStart:vendorEnd])\n\n\treturn vendor, vendorEnd, nil\n}\n\nfunc parseUserComments(payload []byte, vendorEnd, u32Size int) ([]UserComment, error) {\n\tuserCommentCount32 := binary.LittleEndian.Uint32(payload[vendorEnd : vendorEnd+u32Size])\n\tif int(userCommentCount32) > (len(payload)-vendorEnd)/u32Size {\n\t\treturn nil, fmt.Errorf(\"%w: unreasonable comment count\", errBadOpusTagsSignature)","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/pion/webrtc/blob/8c25dc09fa9e7c09aac4309ead88093d760432b0/pkg/media/oggreader/oggreader.go#L409-L445","documentation":"parseVendorString fails when the 32-bit little-endian vendor string length read from the payload exceeds the bytes actually available after the fixed header. The declared vendor string would run past the end of the packet, so the payload is corrupt or truncated; the wrapped errBadOpusTagsSignature sentinel is returned.","triggerScenarios":"ParseOpusTags (or the parseVendorString helper in tests) on a payload whose vendor-length field at offset 8 declares more bytes than len(payload)-minHeaderLen provides — e.g. vendorLen claims 1000 bytes in a 30-byte payload.","commonSituations":"Maliciously or accidentally malformed OpusTags metadata; truncation during download or stream reassembly; a writer bug emitting a wrong length prefix; fuzzing or parsing untrusted media.","solutions":["Re-acquire or re-extract the file/stream; the tags packet is malformed at the source, so re-download or re-mux with a known-good encoder (e.g. ffmpeg).","Verify the Ogg page was fully reassembled (concatenate all pages of the packet) before parsing; do not parse a single short page of a large tags header.","At the call site, match errors.Is(err, ErrBadOpusTagsSignature) and reject/skip the metadata instead of indexing blindly."],"exampleFix":"// before\ntags, err := oggreader.ParseOpusTags(singlePage[:pageLen])\n// after\nfull := assembleFullPacket(pages) // concatenate all Ogg pages of the packet\ntags, err = oggreader.ParseOpusTags(full)","handlingStrategy":"try-catch","validationCode":"if len(payload) >= 12 {\n    declared := int(binary.LittleEndian.Uint32(payload[8:12]))\n    if declared <= len(payload)-12 {\n        tags, err := oggreader.ParseOpusTags(payload)\n    }\n}","typeGuard":null,"tryCatchPattern":"tags, err := oggreader.ParseOpusTags(payload)\nif errors.Is(err, oggreader.ErrBadOpusTagsSignature) {\n    log.Warn(\"malformed OpusTags vendor string; skipping metadata\")\n    return nil, nil // degrade gracefully\n}","preventionTips":["Never trust length fields inside untrusted media; rely on the library's bounds checks and handle the error.","Concatenate all Ogg pages of the comment header before parsing to avoid artificial truncation.","Re-download/re-mux files that fail instead of retrying the same bytes.","Fuzz-test your ingestion path with truncated OpusTags packets to confirm graceful degradation."],"tags":["go","ogg","opus","corrupt-metadata","length-check"],"backgroundTag":"payload-too-short","analyzedSha":"8c25dc09fa9e7c09aac4309ead88093d760432b0","analyzedAt":"2026-09-03T21:56:56.182Z","contentChangedAt":"2026-09-03T21:56:56.182Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}