-
Notifications
You must be signed in to change notification settings - Fork 301
Description
Summary
SymphoniaDecoder::new() panics via unreachable!() when symphonia's FormatReader::next_packet() returns Error::SeekError during initialization. This consistently occurs with M4A (AAC in ISO MP4 container) files.
Affected code — src/decoder/symphonia.rs line 40 (master):
Error::SeekError(_) => {
unreachable!("Seek errors should not occur during initialization")
}Steps to Reproduce
- Obtain an M4A audio file (AAC in ISO MP4 container, e.g. NetEase Cloud Music "exhigh" quality)
- Load the file bytes into memory
- Attempt to decode with any rodio decoder method:
use rodio::Decoder;
use std::io::Cursor;
let audio_bytes: Vec<u8> = std::fs::read("song.m4a").unwrap();
// This panics:
let decoder = Decoder::new(Cursor::new(audio_bytes));The M4A file has a standard ftyp box header: 00 00 00 1c 66 74 79 70 4d 34 41 20 (ftyp + brand M4A ).
Observed Behavior
The program panics with:
thread 'audio' panicked at 'internal error: entered unreachable code: Seek errors should not occur during initialization'
All decoder methods are affected (Decoder::new, Decoder::new_mp3, Decoder::new_flac, Decoder::new_aac, Decoder::new_wav, Decoder::new_vorbis) — they all go through SymphoniaDecoder::init() which calls format.next_packet(), and symphonia's ISO MP4 format reader returns Error::SeekError for these files.
Expected Behavior
Decoder::new() should return Err(DecoderError::...) instead of panicking. A library should never panic on valid user input.
Root Cause
SymphoniaDecoder::init() reads packets in a loop via format.next_packet(). The error handling at the call site (SymphoniaDecoder::new()) assumes SeekError can never be returned during initialization, but symphonia's ISO MP4 FormatReader can return Error::SeekError from next_packet() for certain M4A files.
Suggested Fix
Replace the unreachable!() with a proper error return:
// Before:
Error::SeekError(_) => {
unreachable!("Seek errors should not occur during initialization")
}
// After:
Error::SeekError(e) => Err(DecoderError::IoError(format!("seek error during init: {}", e))),This is a one-line fix. A new DecoderError variant (e.g. SeekError) would be even cleaner but would be a breaking change.
Versions
- rodio: 0.20.1 (also verified on master — the
unreachable!()is still present at line 40) - symphonia: 0.5.5
- OS: Windows 11
- Rust: stable