Skip to content

Commit dd9aa76

Browse files
committed
MP4: Fix panic with improperly sized freeform idents
1 parent e9ec05b commit dd9aa76

File tree

6 files changed

+33
-4
lines changed

6 files changed

+33
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525

2626
### Fixed
2727
- **Fuzzing** (Thanks [@qarmin](https://github.com/qarmin)!) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/TODO)):
28-
- **MP4**: Fix panic when reading properties of a file with no timescale specified ([issue](https://github.com/Serial-ATA/lofty-rs/issues/418))
28+
- **MP4**:
29+
- Fix panic when reading properties of a file with no timescale specified ([issue](https://github.com/Serial-ATA/lofty-rs/issues/418))
30+
- Fix panics when reading improperly sized freeform atom identifiers ([issue](https://github.com/Serial-ATA/lofty-rs/issues/425)) ([issue](https://github.com/Serial-ATA/lofty-rs/issues/426))
2931
- **WAV**: Fix panic when reading properties with large written bytes per second ([issue](https://github.com/Serial-ATA/lofty-rs/issues/420))
3032
- **Vorbis**: Fix panic when reading properties of a file with large absolute granule positions ([issue](https://github.com/Serial-ATA/lofty-rs/issues/421))
3133
- **FLAC**: Fix panic when reading properties of a file with incorrect block sizes ([issue](https://github.com/Serial-ATA/lofty-rs/issues/422))

lofty/src/mp4/atom_info.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl AtomInfo {
192192
err!(BadAtom("Found an incomplete freeform identifier"));
193193
}
194194

195-
atom_ident = parse_freeform(data, reader_size, parse_mode)?;
195+
atom_ident = parse_freeform(data, len, reader_size, parse_mode)?;
196196
} else {
197197
atom_ident = AtomIdent::Fourcc(identifier);
198198
}
@@ -208,12 +208,20 @@ impl AtomInfo {
208208

209209
fn parse_freeform<R>(
210210
data: &mut R,
211+
atom_len: u64,
211212
reader_size: u64,
212213
parse_mode: ParsingMode,
213214
) -> Result<AtomIdent<'static>>
214215
where
215216
R: Read + Seek,
216217
{
218+
// ---- header + mean header + name header = 24
219+
const MINIMUM_FREEFORM_LEN: u64 = ATOM_HEADER_LEN * 3;
220+
221+
if atom_len < MINIMUM_FREEFORM_LEN {
222+
err!(BadAtom("Found an incomplete freeform identifier"));
223+
}
224+
217225
let mean = freeform_chunk(data, b"mean", reader_size, parse_mode)?;
218226
let name = freeform_chunk(data, b"name", reader_size - 4, parse_mode)?;
219227

@@ -240,11 +248,15 @@ where
240248
len,
241249
..
242250
}) if fourcc == name => {
251+
if len < 12 {
252+
err!(BadAtom("Found an incomplete freeform identifier chunk"));
253+
}
254+
243255
// Version (1)
244256
// Flags (3)
245257
data.seek(SeekFrom::Current(4))?;
246258

247-
// Already read the size, identifier, and version/flags (12 bytes)
259+
// Already read the size (4) + identifier (4) + version/flags (4)
248260
let mut content = try_vec![0; (len - 12) as usize];
249261
data.read_exact(&mut content)?;
250262

lofty/src/mp4/ilst/read.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,14 @@ where
212212
// An atom can contain multiple data atoms
213213
let mut ret = Vec::new();
214214

215-
let to_read = (atom_info.start + atom_info.len) - reader.stream_position()?;
215+
let atom_end = atom_info.start + atom_info.len;
216+
let position = reader.stream_position()?;
217+
assert!(
218+
atom_end >= position,
219+
"uncaught size mismatch, reader position: {position} (expected <= {atom_end})",
220+
);
221+
222+
let to_read = atom_end - position;
216223
let mut pos = 0;
217224
while pos < to_read {
218225
let Some(next_atom) = reader.next()? else {

lofty/tests/fuzz/mp4file_read_from.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ fn panic1() {
1515
);
1616
let _ = Mp4File::read_from(&mut reader, ParseOptions::new());
1717
}
18+
19+
#[test]
20+
fn panic2() {
21+
let mut reader = crate::get_reader(
22+
"mp4file_read_from/steam_at_mention_IDX_33_RAND_122808229373977607781108.m4a",
23+
);
24+
let _ = Mp4File::read_from(&mut reader, ParseOptions::new());
25+
}

0 commit comments

Comments
 (0)