Fix for #377 infinite recursion crash (#378)

Implementing the Display trait on a type, and calling self.to_string()
in its implementation results in infinite recursion.

The default implementation of ToString for sized types that implement
Display relies on the Display trait in its implementation.
Consequently, calling `self.to_string()` in the implementation of
Display leads to infinite recursion.

This failure has been directly observed on the DecoderError type, and
the fix here is to move the logic for rendering the error as text out of
`Error::description()` and into `impl Display`. As it stands, the
`Error` trait provides a default implementation for `description()`
based on the `Display` trait if provided, so this is a simple, clean
change.

The failure is presumed to exist for Mp4Type, as it follows a similar
pattern of invoking `self.to_string()` in the `Display` implementation.
The solution there is basically to reverse the logic for `from_str()`.
This commit is contained in:
Will Page 2021-06-30 08:05:41 -07:00 committed by GitHub
parent 0988e8c886
commit edc60950b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -230,8 +230,16 @@ impl FromStr for Mp4Type {
impl fmt::Display for Mp4Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let res = self.to_string().to_lowercase();
write!(f, "{}", res)
let text = match self {
Mp4Type::Mp4 => "mp4",
Mp4Type::M4a => "m4a",
Mp4Type::M4p => "m4p",
Mp4Type::M4b => "m4b",
Mp4Type::M4r => "m4r",
Mp4Type::M4v => "m4v",
Mp4Type::Mov => "mov",
};
write!(f, "{}", text)
}
}
@ -542,13 +550,7 @@ pub enum DecoderError {
impl fmt::Display for DecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_string())
}
}
impl Error for DecoderError {
fn description(&self) -> &str {
match self {
let text = match self {
DecoderError::UnrecognizedFormat => "Unrecognized format",
#[cfg(feature = "symphonia")]
DecoderError::IoError(msg) => &msg[..],
@ -560,6 +562,9 @@ impl Error for DecoderError {
DecoderError::ResetRequired => "Reset required",
#[cfg(feature = "symphonia")]
DecoderError::NoStreams => "No streams",
}
};
write!(f, "{}", text)
}
}
impl Error for DecoderError {}