meta: Return io.ErrUnexpectedEOF if EOF occurs in the middle of a metadata block.
This commit is contained in:
parent
ddd621f24d
commit
7a33256cf7
|
@ -189,8 +189,8 @@ func (frame *Frame) parseHeader() error {
|
|||
frame.br = br
|
||||
x, err := br.Read(14)
|
||||
if err != nil {
|
||||
// This should be the only place for a frame to return io.EOF, which
|
||||
// signals a graceful end of FLAC stream.
|
||||
// This is the only place an audio frame may return io.EOF, which signals
|
||||
// a graceful end of a FLAC stream.
|
||||
return err
|
||||
}
|
||||
if x != 0x3FFE {
|
||||
|
|
|
@ -24,7 +24,7 @@ func (block *Block) parseApplication() error {
|
|||
block.Body = app
|
||||
err := binary.Read(block.lr, binary.BigEndian, &app.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// Check if the Application block only contains an ID.
|
||||
|
@ -34,5 +34,5 @@ func (block *Block) parseApplication() error {
|
|||
|
||||
// (block length)-4 bytes: Data.
|
||||
app.Data, err = ioutil.ReadAll(block.lr)
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func (block *Block) parseCueSheet() error {
|
|||
// 128 bytes: MCN.
|
||||
buf, err := readBytes(block.lr, 128)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
cs := new(CueSheet)
|
||||
block.Body = cs
|
||||
|
@ -41,14 +41,14 @@ func (block *Block) parseCueSheet() error {
|
|||
// 64 bits: NLeadInSamples.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &cs.NLeadInSamples)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 1 bit: IsCompactDisc.
|
||||
var x uint8
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
// mask = 10000000
|
||||
if x&0x80 != 0 {
|
||||
|
@ -71,7 +71,7 @@ func (block *Block) parseCueSheet() error {
|
|||
// 8 bits: (number of tracks)
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x < 1 {
|
||||
return errors.New("meta.Block.parseCueSheet: at least one track required")
|
||||
|
@ -88,7 +88,7 @@ func (block *Block) parseCueSheet() error {
|
|||
track := &cs.Tracks[i]
|
||||
err = binary.Read(block.lr, binary.BigEndian, &track.Offset)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if cs.IsCompactDisc && track.Offset%588 != 0 {
|
||||
return fmt.Errorf("meta.Block.parseCueSheet: CD-DA track offset (%d) must be evenly divisible by 588", track.Offset)
|
||||
|
@ -97,7 +97,7 @@ func (block *Block) parseCueSheet() error {
|
|||
// 8 bits: Num.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &track.Num)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if _, ok := uniq[track.Num]; ok {
|
||||
return fmt.Errorf("meta.Block.parseCueSheet: duplicated track number %d", track.Num)
|
||||
|
@ -126,14 +126,14 @@ func (block *Block) parseCueSheet() error {
|
|||
// 12 bytes: ISRC.
|
||||
buf, err = readBytes(block.lr, 12)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
track.ISRC = stringFromSZ(buf)
|
||||
|
||||
// 1 bit: IsAudio.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
// mask = 10000000
|
||||
if x&0x80 == 0 {
|
||||
|
@ -162,7 +162,7 @@ func (block *Block) parseCueSheet() error {
|
|||
// 8 bits: (number of indicies)
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x < 1 {
|
||||
if !isLeadOut {
|
||||
|
@ -176,13 +176,13 @@ func (block *Block) parseCueSheet() error {
|
|||
// 64 bits: Offset.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &index.Offset)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 8 bits: Num.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &index.Num)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 3 bytes: reserved.
|
||||
|
|
24
meta/meta.go
24
meta/meta.go
|
@ -1,6 +1,3 @@
|
|||
// TODO(u): Return io.ErrUnexpectedEOF if EOF occurs in the middle of a metadata
|
||||
// block.
|
||||
|
||||
// Package meta implements access to FLAC metadata blocks.
|
||||
//
|
||||
// A brief introduction of the FLAC metadata format [1] follows. FLAC metadata
|
||||
|
@ -139,6 +136,14 @@ func (block *Block) parseHeader(r io.Reader) error {
|
|||
br := bit.NewReader(r)
|
||||
x, err := br.Read(1)
|
||||
if err != nil {
|
||||
// This is the only place a metadata block may return io.EOF, which
|
||||
// signals a graceful end of a FLAC stream (from a metadata point of
|
||||
// view).
|
||||
//
|
||||
// Note that valid FLAC streams always contain at least one audio frame
|
||||
// after the last metadata block. Therefore an io.EOF error at this
|
||||
// location is always invalid. This logic is to be handled by the flac
|
||||
// package however.
|
||||
return err
|
||||
}
|
||||
if x != 0 {
|
||||
|
@ -148,14 +153,14 @@ func (block *Block) parseHeader(r io.Reader) error {
|
|||
// 7 bits: Type.
|
||||
x, err = br.Read(7)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
block.Type = Type(x)
|
||||
|
||||
// 24 bits: Length.
|
||||
x, err = br.Read(24)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
block.Length = int64(x)
|
||||
|
||||
|
@ -175,3 +180,12 @@ const (
|
|||
TypeCueSheet
|
||||
TypePicture
|
||||
)
|
||||
|
||||
// unexpected returns io.ErrUnexpectedEOF if err is io.EOF, and returns err
|
||||
// otherwise.
|
||||
func unexpected(err error) error {
|
||||
if err == io.EOF {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -57,68 +57,71 @@ func (block *Block) parsePicture() error {
|
|||
block.Body = pic
|
||||
err := binary.Read(block.lr, binary.BigEndian, &pic.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 32 bits: (MIME type length).
|
||||
var x uint32
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// (MIME type length) bytes: MIMEType.
|
||||
buf, err := readBytes(block.lr, int(x))
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
pic.MIMEType = string(buf)
|
||||
|
||||
// 32 bits: (description length).
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// (description length) bytes: Desc.
|
||||
buf, err = readBytes(block.lr, int(x))
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
pic.Desc = string(buf)
|
||||
|
||||
// 32 bits: Width.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &pic.Width)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 32 bits: Height.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &pic.Height)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 32 bits: Depth.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &pic.Depth)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 32 bits: NPalColors.
|
||||
err = binary.Read(block.lr, binary.BigEndian, &pic.NPalColors)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 32 bits: (data length).
|
||||
err = binary.Read(block.lr, binary.BigEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// (data length) bytes: Data.
|
||||
pic.Data = make([]byte, x)
|
||||
_, err = io.ReadFull(block.lr, pic.Data)
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ var readBuf = make([]byte, 4096)
|
|||
|
||||
// readBytes reads and returns exactly n bytes from the provided io.Reader. The
|
||||
// local buffer is reused in between calls to reduce garbage generation. It is
|
||||
// the callers responsibility to make a copy of the returned data.
|
||||
// the callers responsibility to make a copy of the returned data. The error is
|
||||
// io.EOF only if no bytes were read. If an io.EOF happens after reading some
|
||||
// but not all the bytes, ReadFull returns io.ErrUnexpectedEOF. On return, n ==
|
||||
// len(buf) if and only if err == nil.
|
||||
//
|
||||
// The local buffer is initially 4096 bytes and will grow automatically if so
|
||||
// required.
|
||||
|
|
|
@ -29,7 +29,7 @@ func (block *Block) parseSeekTable() error {
|
|||
point := &table.Points[i]
|
||||
err := binary.Read(block.lr, binary.BigEndian, point)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
// Seek points within a table must be sorted in ascending order by sample
|
||||
// number. Each seek point must have a unique sample number, except for
|
||||
|
|
|
@ -45,7 +45,7 @@ func (block *Block) parseStreamInfo() error {
|
|||
br := bit.NewReader(block.lr)
|
||||
x, err := br.Read(16)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x < 16 {
|
||||
return fmt.Errorf("meta.Block.parseStreamInfo: invalid minimum block size (%d); expected >= 16", x)
|
||||
|
@ -57,7 +57,7 @@ func (block *Block) parseStreamInfo() error {
|
|||
// 16 bits: BlockSizeMax.
|
||||
x, err = br.Read(16)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x < 16 {
|
||||
return fmt.Errorf("meta.Block.parseStreamInfo: invalid maximum block size (%d); expected >= 16", x)
|
||||
|
@ -67,21 +67,21 @@ func (block *Block) parseStreamInfo() error {
|
|||
// 24 bits: FrameSizeMin.
|
||||
x, err = br.Read(24)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
si.FrameSizeMin = uint32(x)
|
||||
|
||||
// 24 bits: FrameSizeMax.
|
||||
x, err = br.Read(24)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
si.FrameSizeMax = uint32(x)
|
||||
|
||||
// 20 bits: SampleRate.
|
||||
x, err = br.Read(20)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x == 0 {
|
||||
return errors.New("meta.Block.parseStreamInfo: invalid sample rate (0)")
|
||||
|
@ -91,7 +91,7 @@ func (block *Block) parseStreamInfo() error {
|
|||
// 3 bits: NChannels.
|
||||
x, err = br.Read(3)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
// x contains: (number of channels) - 1
|
||||
si.NChannels = uint8(x + 1)
|
||||
|
@ -99,7 +99,7 @@ func (block *Block) parseStreamInfo() error {
|
|||
// 5 bits: BitsPerSample.
|
||||
x, err = br.Read(5)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
// x contains: (bits-per-sample) - 1
|
||||
si.BitsPerSample = uint8(x + 1)
|
||||
|
@ -107,10 +107,10 @@ func (block *Block) parseStreamInfo() error {
|
|||
// 36 bits: NSamples.
|
||||
si.NSamples, err = br.Read(36)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// 16 bytes: MD5sum.
|
||||
_, err = io.ReadFull(block.lr, si.MD5sum[:])
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ func (block *Block) parseVorbisComment() error {
|
|||
var x uint32
|
||||
err := binary.Read(block.lr, binary.LittleEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// (vendor length) bits: Vendor.
|
||||
buf, err := readBytes(block.lr, int(x))
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
comment := new(VorbisComment)
|
||||
block.Body = comment
|
||||
|
@ -39,7 +39,7 @@ func (block *Block) parseVorbisComment() error {
|
|||
// 32 bits: number of tags.
|
||||
err = binary.Read(block.lr, binary.LittleEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
if x < 1 {
|
||||
return nil
|
||||
|
@ -49,13 +49,13 @@ func (block *Block) parseVorbisComment() error {
|
|||
// 32 bits: vector length
|
||||
err = binary.Read(block.lr, binary.LittleEndian, &x)
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
|
||||
// (vector length): vector.
|
||||
buf, err = readBytes(block.lr, int(x))
|
||||
if err != nil {
|
||||
return err
|
||||
return unexpected(err)
|
||||
}
|
||||
vector := string(buf)
|
||||
|
||||
|
|
Loading…
Reference in a new issue