From c1716d552184d8cd825dc693ab20e47115c689fb Mon Sep 17 00:00:00 2001 From: Xavier Henner Date: Sun, 26 Apr 2015 16:56:26 +0200 Subject: [PATCH 1/3] take into account h.Unsynchronisation and add some sanity check --- id3v2.go | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/id3v2.go b/id3v2.go index 32017b9..5d333f1 100644 --- a/id3v2.go +++ b/id3v2.go @@ -166,6 +166,12 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error if err != nil { return nil, err } + // if size=0, we certainly are in a padding zone. ignore the rest of + // the tags. and if size > h.Size, we have a problem + if size == 0 || size > h.Size { + break + } + offset += headerSize + size // Check this stuff out... @@ -220,6 +226,29 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error return result, nil } +type Unsynchroniser struct { + orig io.Reader +} + +// filter io.Reader which skip the Unsynchronisation bytes +func (r *Unsynchroniser) Read(p []byte) (int, error) { + nextOk := false + for i := 0; i < len(p); i++ { + if n, err := r.orig.Read(p[i : i+1]); n == 0 || err != nil { + return i, err + } + if i >= 1 && p[i-1] == 255 && p[i] == 0 && !nextOk { + // we must skip this 00 + i-- + // but not the next one + nextOk = true + } else { + nextOk = false + } + } + return len(p), nil +} + // ReadID3v2Tags parses ID3v2.{2,3,4} tags from the io.ReadSeeker into a Metadata, returning // non-nil error on failure. func ReadID3v2Tags(r io.ReadSeeker) (Metadata, error) { @@ -232,7 +261,16 @@ func ReadID3v2Tags(r io.ReadSeeker) (Metadata, error) { if err != nil { return nil, err } - f, err := readID3v2Frames(r, h) + + var ur io.Reader + + if h.Unsynchronisation { + ur = &Unsynchroniser{orig: r} + } else { + ur = r + } + + f, err := readID3v2Frames(ur, h) if err != nil { return nil, err } From dad1548722e32cabdc898e8c17c2a190e5cf8d22 Mon Sep 17 00:00:00 2001 From: Xavier Henner Date: Thu, 30 Apr 2015 22:07:08 +0200 Subject: [PATCH 2/3] Need to skip Unsynchronisation byte at the boundary between 2 Read --- id3v2.go | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/id3v2.go b/id3v2.go index 5d333f1..82b4b97 100644 --- a/id3v2.go +++ b/id3v2.go @@ -167,8 +167,8 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error return nil, err } // if size=0, we certainly are in a padding zone. ignore the rest of - // the tags. and if size > h.Size, we have a problem - if size == 0 || size > h.Size { + // the tags + if size == 0 { break } @@ -227,24 +227,41 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error } type Unsynchroniser struct { - orig io.Reader + orig io.Reader + prevWasFF bool } // filter io.Reader which skip the Unsynchronisation bytes func (r *Unsynchroniser) Read(p []byte) (int, error) { - nextOk := false for i := 0; i < len(p); i++ { - if n, err := r.orig.Read(p[i : i+1]); n == 0 || err != nil { + // there is only one byte to read. + if i == len(p)-1 { + if n, err := r.orig.Read(p[i : i+1]); n == 0 || err != nil { + return i, err + } + // we need to read this last byte once more + if r.prevWasFF && p[i] == 0 { + i-- + r.prevWasFF = false + } + r.prevWasFF = (p[i] == 255) + continue + } + if n, err := r.orig.Read(p[i : i+2]); n == 0 || err != nil { return i, err } - if i >= 1 && p[i-1] == 255 && p[i] == 0 && !nextOk { - // we must skip this 00 - i-- - // but not the next one - nextOk = true - } else { - nextOk = false + if r.prevWasFF && p[i] == 0 { + p[i] = p[i+1] + r.prevWasFF = false + continue } + if p[i] == 255 && p[i+1] == 0 { + r.prevWasFF = false + continue + } + r.prevWasFF = (p[i+1] == 255) + // these 2 bytes are fine, we skip none + i++ } return len(p), nil } From cac0ed8f5709740950e0ccfa02cedf328a02beb4 Mon Sep 17 00:00:00 2001 From: Xavier Henner Date: Fri, 1 May 2015 00:55:17 +0200 Subject: [PATCH 3/3] now work with 'ff 00 ff 00' in the file --- id3v2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/id3v2.go b/id3v2.go index 82b4b97..806d23b 100644 --- a/id3v2.go +++ b/id3v2.go @@ -252,7 +252,7 @@ func (r *Unsynchroniser) Read(p []byte) (int, error) { } if r.prevWasFF && p[i] == 0 { p[i] = p[i+1] - r.prevWasFF = false + r.prevWasFF = (p[i+1] == 255) continue } if p[i] == 255 && p[i+1] == 0 {