fix(voice): bound header slice when seeking truncated audio
This commit is contained in:
parent
f647d96fab
commit
9c1a39ca76
2 changed files with 34 additions and 19 deletions
|
|
@ -125,7 +125,7 @@ func (p *Player) seek(position time.Duration) error {
|
|||
offset += size
|
||||
}
|
||||
|
||||
decoder, err := oggopus.NewDecoder(io.MultiReader(bytes.NewReader(p.audio[:headers]), bytes.NewReader(p.audio[min(start, len(p.audio)):])))
|
||||
decoder, err := oggopus.NewDecoder(io.MultiReader(bytes.NewReader(p.audio[:min(headers, len(p.audio))]), bytes.NewReader(p.audio[min(start, len(p.audio)):])))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,28 +12,43 @@ import (
|
|||
)
|
||||
|
||||
func TestPlayerSeek(t *testing.T) {
|
||||
const seconds = 10
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
const seconds = 10
|
||||
|
||||
var audio bytes.Buffer
|
||||
if err := oggopus.EncodeInterleaved(&audio, oggopus.Config{SampleRate: sampleRate, Channels: 1}, make([]byte, seconds*sampleRate*2)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := Player{audio: audio.Bytes()}
|
||||
for _, position := range []time.Duration{0, 500 * time.Millisecond, 6 * time.Second, seconds * time.Second, time.Hour} {
|
||||
if err := p.seek(position); err != nil {
|
||||
var audio bytes.Buffer
|
||||
if err := oggopus.EncodeInterleaved(&audio, oggopus.Config{SampleRate: sampleRate, Channels: 1}, make([]byte, seconds*sampleRate*2)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
left, err := io.Copy(io.Discard, p.decoder)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
p := Player{audio: audio.Bytes()}
|
||||
for _, position := range []time.Duration{0, 500 * time.Millisecond, 6 * time.Second, seconds * time.Second, time.Hour} {
|
||||
if err := p.seek(position); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
left, err := io.Copy(io.Discard, p.decoder)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// What is left is a packet longer at most, as the end is only trimmed when played from the start.
|
||||
want := max(seconds*time.Second-position, 0)
|
||||
if got := time.Duration(left/2) * time.Second / sampleRate; got < want || got > want+20*time.Millisecond {
|
||||
t.Errorf("seek to %v: %v is left, want %v", position, got, want)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// A page whose segment table claims far more bytes than the file holds must not make seek read out of bounds.
|
||||
t.Run("truncated page", func(t *testing.T) {
|
||||
page := make([]byte, oggHeaderSize+255)
|
||||
copy(page, "OggS")
|
||||
page[oggSegmentsOffset] = 255
|
||||
for i := range page[oggHeaderSize:] {
|
||||
page[oggHeaderSize+i] = 255
|
||||
}
|
||||
|
||||
// What is left is a packet longer at most, as the end is only trimmed when played from the start.
|
||||
want := max(seconds*time.Second-position, 0)
|
||||
if got := time.Duration(left/2) * time.Second / sampleRate; got < want || got > want+20*time.Millisecond {
|
||||
t.Errorf("seek to %v: %v is left, want %v", position, got, want)
|
||||
}
|
||||
}
|
||||
p := Player{audio: page}
|
||||
_ = p.seek(0)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue