From 010b60b88911a5fe6fee18ccf50a5dde2f67819a Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sun, 2 Jan 2022 20:53:26 -0500 Subject: [PATCH] Fix MP3 panic, add fuzz targets --- fuzz/.gitignore | 3 ++ fuzz/Cargo.toml | 55 +++++++++++++++++++++++ fuzz/fuzz_targets/aifffile_read_from.rs | 10 +++++ fuzz/fuzz_targets/apefile_read_from.rs | 10 +++++ fuzz/fuzz_targets/filetype_from_buffer.rs | 6 +++ fuzz/fuzz_targets/flacfile_read_from.rs | 10 +++++ fuzz/fuzz_targets/mp3file_read_from.rs | 10 +++++ fuzz/fuzz_targets/mp4file_read_from.rs | 10 +++++ fuzz/fuzz_targets/opusfile_read_from.rs | 10 +++++ fuzz/fuzz_targets/vorbisfile_read_from.rs | 10 +++++ fuzz/fuzz_targets/wavfile_read_from.rs | 10 +++++ src/mp3/header.rs | 11 +++-- src/mp3/read.rs | 5 +++ 13 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Cargo.toml create mode 100644 fuzz/fuzz_targets/aifffile_read_from.rs create mode 100644 fuzz/fuzz_targets/apefile_read_from.rs create mode 100644 fuzz/fuzz_targets/filetype_from_buffer.rs create mode 100644 fuzz/fuzz_targets/flacfile_read_from.rs create mode 100644 fuzz/fuzz_targets/mp3file_read_from.rs create mode 100644 fuzz/fuzz_targets/mp4file_read_from.rs create mode 100644 fuzz/fuzz_targets/opusfile_read_from.rs create mode 100644 fuzz/fuzz_targets/vorbisfile_read_from.rs create mode 100644 fuzz/fuzz_targets/wavfile_read_from.rs diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000..a0925114 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,3 @@ +target +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 00000000..518271ff --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "lofty-fuzz" +version = "0.0.0" +authors = ["Automatically generated"] +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.lofty] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "filetype_from_buffer" +path = "fuzz_targets/filetype_from_buffer.rs" + +[[bin]] +name = "mp3file_read_from" +path = "fuzz_targets/mp3file_read_from.rs" + +[[bin]] +name = "aifffile_read_from" +path = "fuzz_targets/aifffile_read_from.rs" + +[[bin]] +name = "apefile_read_from" +path = "fuzz_targets/apefile_read_from.rs" + +[[bin]] +name = "flacfile_read_from" +path = "fuzz_targets/flacfile_read_from.rs" + +[[bin]] +name = "mp4file_read_from" +path = "fuzz_targets/mp4file_read_from.rs" + +[[bin]] +name = "opusfile_read_from" +path = "fuzz_targets/opusfile_read_from.rs" + +[[bin]] +name = "vorbisfile_read_from" +path = "fuzz_targets/vorbisfile_read_from.rs" + +[[bin]] +name = "wavfile_read_from" +path = "fuzz_targets/wavfile_read_from.rs" \ No newline at end of file diff --git a/fuzz/fuzz_targets/aifffile_read_from.rs b/fuzz/fuzz_targets/aifffile_read_from.rs new file mode 100644 index 00000000..0b26c0e3 --- /dev/null +++ b/fuzz/fuzz_targets/aifffile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::iff::AiffFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/apefile_read_from.rs b/fuzz/fuzz_targets/apefile_read_from.rs new file mode 100644 index 00000000..9e2fb89f --- /dev/null +++ b/fuzz/fuzz_targets/apefile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::ape::ApeFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/filetype_from_buffer.rs b/fuzz/fuzz_targets/filetype_from_buffer.rs new file mode 100644 index 00000000..891e9f88 --- /dev/null +++ b/fuzz/fuzz_targets/filetype_from_buffer.rs @@ -0,0 +1,6 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + let _ = lofty::FileType::from_buffer(data); +}); diff --git a/fuzz/fuzz_targets/flacfile_read_from.rs b/fuzz/fuzz_targets/flacfile_read_from.rs new file mode 100644 index 00000000..ff16cdf6 --- /dev/null +++ b/fuzz/fuzz_targets/flacfile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::ogg::FlacFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/mp3file_read_from.rs b/fuzz/fuzz_targets/mp3file_read_from.rs new file mode 100644 index 00000000..56637b8a --- /dev/null +++ b/fuzz/fuzz_targets/mp3file_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::mp3::Mp3File::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/mp4file_read_from.rs b/fuzz/fuzz_targets/mp4file_read_from.rs new file mode 100644 index 00000000..a887e44a --- /dev/null +++ b/fuzz/fuzz_targets/mp4file_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::mp4::Mp4File::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/opusfile_read_from.rs b/fuzz/fuzz_targets/opusfile_read_from.rs new file mode 100644 index 00000000..634bd8f4 --- /dev/null +++ b/fuzz/fuzz_targets/opusfile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::ogg::OpusFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/vorbisfile_read_from.rs b/fuzz/fuzz_targets/vorbisfile_read_from.rs new file mode 100644 index 00000000..034183e7 --- /dev/null +++ b/fuzz/fuzz_targets/vorbisfile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::ogg::VorbisFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/fuzz/fuzz_targets/wavfile_read_from.rs b/fuzz/fuzz_targets/wavfile_read_from.rs new file mode 100644 index 00000000..4e69df13 --- /dev/null +++ b/fuzz/fuzz_targets/wavfile_read_from.rs @@ -0,0 +1,10 @@ +#![no_main] + +use std::io::Cursor; + +use lofty::AudioFile; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: Vec| { + let _ = lofty::iff::WavFile::read_from(&mut Cursor::new(data), false); +}); diff --git a/src/mp3/header.rs b/src/mp3/header.rs index fdb1892a..6f7e0ba3 100644 --- a/src/mp3/header.rs +++ b/src/mp3/header.rs @@ -96,6 +96,7 @@ impl Header { match sample_rate { // This is invalid, but it doesn't seem worth it to error here + // We will error if properties are read 3 => sample_rate = 0, _ => sample_rate = SAMPLE_RATES[version as usize][sample_rate as usize], } @@ -118,9 +119,13 @@ impl Header { let data_start = SIDE_INFORMATION_SIZES[version_index][channel_mode as usize] + 4; let samples = SAMPLES[layer_index][version_index]; - let len = match layer { - Layer::Layer1 => (bitrate * 12000 / sample_rate + padding) * 4, - Layer::Layer2 | Layer::Layer3 => bitrate * 144_000 / sample_rate + padding, + let len = if sample_rate == 0 { + 0 + } else { + match layer { + Layer::Layer1 => (bitrate * 12000 / sample_rate + padding) * 4, + Layer::Layer2 | Layer::Layer3 => bitrate * 144_000 / sample_rate + padding, + } }; let channels = if channel_mode == ChannelMode::SingleChannel { diff --git a/src/mp3/read.rs b/src/mp3/read.rs index 5e4bcbcd..87ad571a 100644 --- a/src/mp3/read.rs +++ b/src/mp3/read.rs @@ -131,6 +131,11 @@ where } let first_frame_header = first_frame_header.unwrap(); + + if first_frame_header.sample_rate == 0 { + return Err(LoftyError::Mp3("Sample rate is 0")); + } + let first_frame_offset = file.first_frame_offset.unwrap(); let file_length = reader.seek(SeekFrom::End(0))?;