go-mp3 icon indicating copy to clipboard operation
go-mp3 copied to clipboard

Intermittent "Slice bounds out of range" during decoding

Open nathanKramer opened this issue 4 years ago • 5 comments

I have noticed an intermittent panic error that occurs during decoding. This happens specifically when seek is called several times in quick succession. (e.g rapidly clicking). It might be appropriate to debounce seeking, however I thought I'd raise this anyway as I'm not sure.

panic: runtime error: slice bounds out of range [5696:4608]

The panic occurs here:

https://github.com/hajimehoshi/go-mp3/blob/cc618d12977d7de5f0251f47fad52517fa65a413/decode.go#L102

I can reproduce this using the following faiface/beep code. It seems possible that this is a bug within beep. I don't understand the situation well enough so I have decided to at least put this on your radar.

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/faiface/beep"
	"github.com/faiface/beep/mp3"
	"github.com/faiface/beep/speaker"
)

var soundFormat *beep.Format
var musicStreamer *beep.StreamSeekCloser

func prepareStreamer(file string) (*beep.StreamSeekCloser, *beep.Format) {
	sound, _ := os.Open(file)
	streamer, format, err := mp3.Decode(sound)
	if err != nil {
		panic(err)
	}
	return &streamer, &format
}

func main() {
	musicStreamer, soundFormat = prepareStreamer("an.mp3")
	speaker.Init(soundFormat.SampleRate, soundFormat.SampleRate.N(time.Second/10))

	speaker.Clear()
	s := *musicStreamer
	s.Seek(0)
	speaker.Play(s)

	ch := make(chan int)
	go func() {
		for true {
			time.Sleep(250 * time.Millisecond)
			fmt.Println("seeking")
			streamer := *musicStreamer
			streamer.Seek(700000) // anywhere into the song
		}
	}()
	<-ch

	defer s.Close()
}

One way to fix this:

bufLength := int64(len(d.buf))
idx := d.bytesPerFrame + (d.pos % d.bytesPerFrame)
if idx > bufLength {
	idx = bufLength
}

However I don't understand the underlying cause so there may be a better solution.

nathanKramer avatar Aug 25 '20 02:08 nathanKramer

Thanks. Unfortunately I don't fully understand the implementation details because I just ported the existing MP3 decoder to Go. I'll take a look but I'm not sure I can find a correct fix.

hajimehoshi avatar Aug 25 '20 03:08 hajimehoshi

This part seems what I wrote. I'll take a look.

hajimehoshi avatar Sep 02 '20 15:09 hajimehoshi

  	streamer.Seek(700000) // anywhere into the song

Isn't this simply out of range? Or, was this error happening with any position?

hajimehoshi avatar Sep 02 '20 15:09 hajimehoshi

Isn't this simply out of range? Or, was this error happening with any position?

No, it wasn't out of range, and yes it seems to happen with any position. It seemed to happen randomly. The code to reproduce is meant to emulate a user clicking once every 250ms, as this was the original way I found the issue.

nathanKramer avatar Sep 03 '20 10:09 nathanKramer

This bug still occurs frequently as of 2023 April. I am trying to change the seeker progress with a GUI slidebar, but it crashes if I send the request too frequently. It is always the message:

panic: runtime error: slice bounds out of range [????:4608]. Notice the slice size is always capped at the magic number 4608

evanhyd avatar Apr 02 '23 16:04 evanhyd