grafov / m3u8

Parser and generator of M3U8-playlists for Apple HLS. Library for Go language. :cinema:
http://tools.ietf.org/html/draft-pantos-http-live-streaming
BSD 3-Clause "New" or "Revised" License
1.22k stars 312 forks source link

m3u8.DecodeFrom panics in case of blank lines in playlist #166

Open vany-egorov opened 3 years ago

vany-egorov commented 3 years ago
package main

import (
    "bytes"

    "github.com/grafov/m3u8"
)

func main() {
    raw := []byte(`#EXTM3U
#EXT-X-VERSION:2
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:2718

#EXT-X-KEY:METHOD=NONE

#EXTINF:6,
stream300k2020_9_22_12_41_58-2718.ts
#EXTINF:7,
stream300k2020_9_22_12_42_5-2719.ts
#EXTINF:6,
stream300k2020_9_22_12_42_11-2720.ts
#EXTINF:6,
stream300k2020_9_22_12_42_18-2721.ts
#EXTINF:6,
stream300k2020_9_22_12_42_24-2722.ts
#EXTINF:6,
stream300k2020_9_22_12_42_30-2723.ts
#EXTINF:6,
stream300k2020_9_22_12_42_37-2724.ts
#EXTINF:6,
stream300k2020_9_22_12_42_43-2725.ts
#EXTINF:6,
stream300k2020_9_22_12_42_50-2726.ts
#EXTINF:6,
stream300k2020_9_22_12_42_56-2727.ts`)

    buf := bytes.NewBuffer(raw)

    m3u8.DecodeFrom(buf, false)
}
go run ./m3u8-with-new-lines.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4e2357]

goroutine 1 [running]:
github.com/grafov/m3u8.decodeLineOfMediaPlaylist(0xc0000d6000, 0xc0000d4000, 0xc000093e00, 0x5cc4f0, 0x1, 0x0, 0x0, 0x0)
        gopath/pkg/mod/github.com/grafov/m3u8@v0.11.1/reader.go:539 +0x3537
github.com/grafov/m3u8.decode(0xc000093ef8, 0x53ce00, 0x0, 0x0, 0x0, 0x0, 0x4fdb80, 0xc000096250, 0xc000093f18, 0xc000093f20)
        gopath/pkg/mod/github.com/grafov/m3u8@v0.11.1/reader.go:227 +0x30a
github.com/grafov/m3u8.DecodeFrom(0x53cec0, 0xc000098240, 0x406000, 0xc000094058, 0x0, 0x0, 0x0, 0x4f5ca0)
        gopath/pkg/mod/github.com/grafov/m3u8@v0.11.1/reader.go:161 +0xca
main.main()
        m3u8-with-new-lines.go:41 +0xc5
exit status 2
$ go version
go version go1.15.1 linux/amd64

Very fast hack/work-around:

package main

import (
    "bytes"
    "fmt"
    "regexp"

    "github.com/grafov/m3u8"
)

var reBlankLines = regexp.MustCompile(`[\t\r\n]+`)

func removeBlankLinesFromBuffer(buf *bytes.Buffer) {
    data := buf.Bytes()
    if reBlankLines.Match(data) {
        data = reBlankLines.ReplaceAll(
            bytes.TrimSpace(buf.Bytes()),
            []byte("\n"),
        )
        buf.Reset()
        buf.Write(data)
    }
}

func main() {
    raw := []byte(`#EXTM3U
#EXT-X-VERSION:2
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:2718

#EXT-X-KEY:METHOD=NONE

#EXTINF:6,
stream300k2020_9_22_12_41_58-2718.ts
#EXTINF:7,
stream300k2020_9_22_12_42_5-2719.ts
#EXTINF:6,
stream300k2020_9_22_12_42_11-2720.ts
#EXTINF:6,
stream300k2020_9_22_12_42_18-2721.ts
#EXTINF:6,
stream300k2020_9_22_12_42_24-2722.ts
#EXTINF:6,
stream300k2020_9_22_12_42_30-2723.ts
#EXTINF:6,
stream300k2020_9_22_12_42_37-2724.ts
#EXTINF:6,
stream300k2020_9_22_12_42_43-2725.ts
#EXTINF:6,
stream300k2020_9_22_12_42_50-2726.ts
#EXTINF:6,
stream300k2020_9_22_12_42_56-2727.ts`)

    buf := bytes.NewBuffer(raw)

    removeBlankLinesFromBuffer(buf)

    p, t, err := m3u8.DecodeFrom(buf, false)
    fmt.Println(p, t, err)
}