format: fix the hls-ts media-sequence decode bound

Ingest admits mediaSequence up to MaxInt64-(count-1), but the payload
decoder rejected anything above MaxInt64-count, so a boundary playlist
ingested successfully and then failed every view. Mirror the ingest
bound, covered by a round-trip test at the boundary.
This commit is contained in:
Chris Lu
2026-08-10 17:22:54 -07:00
parent 79297b549e
commit b65bcd4afa
2 changed files with 24 additions and 1 deletions
+2 -1
View File
@@ -67,8 +67,9 @@ func decodePlaylistInfo(payload []byte, extentCount int) (*playlistInfo, error)
if err != nil || target == 0 || target > math.MaxInt32 {
return nil, fmt.Errorf("invalid hls-ts target duration")
}
// mirror the ingest bound: the last segment number is sequence+count-1
sequence, err := binary.ReadUvarint(reader)
if err != nil || sequence > math.MaxInt64-uint64(extentCount) {
if err != nil || sequence > math.MaxInt64-uint64(extentCount-1) {
return nil, fmt.Errorf("invalid hls-ts media sequence")
}
info := &playlistInfo{TargetDuration: int64(target), MediaSequence: int64(sequence), DurationsMs: make([]int64, extentCount)}
+22
View File
@@ -168,6 +168,28 @@ func TestViewSegmentHonorsMediaSequence(t *testing.T) {
}
}
// The ingest bound admits mediaSequence = MaxInt64-(count-1); the payload
// decoder must accept the same boundary or every view of such an asset fails.
func TestMediaSequenceBoundaryRoundTrip(t *testing.T) {
playlist := "#EXTM3U\n#EXT-X-MEDIA-SEQUENCE:9223372036854775806\n" +
"#EXTINF:6,\n#EXT-X-BYTERANGE:188@0\nv.ts\n#EXTINF:6,\n#EXT-X-BYTERANGE:188\nv.ts\n#EXT-X-ENDLIST\n"
layout, err := Adapter{}.IndexSidecar([]byte(playlist))
if err != nil {
t.Fatalf("IndexSidecar() error = %v", err)
}
obj := format.Object{Name: "v.ts", Size: layout.TotalSize(), Layout: layout}
if _, err := (Adapter{}).View(format.ViewRequest{Query: url.Values{}}, obj); err != nil {
t.Fatalf("playlist view error = %v", err)
}
plan, err := Adapter{}.View(format.ViewRequest{Query: url.Values{"seq": {"9223372036854775807"}}}, obj)
if err != nil {
t.Fatalf("last segment view error = %v", err)
}
if plan.Extent != 1 {
t.Fatalf("Extent = %d, want 1", plan.Extent)
}
}
func TestSniff(t *testing.T) {
head := make([]byte, 400)
head[0], head[TSPacketSize] = tsSyncByte, tsSyncByte