From d23c7599d263de1016942a1d6c4d329572f23987 Mon Sep 17 00:00:00 2001 From: Maurice Fisher Date: Thu, 3 Aug 2023 10:01:25 -0400 Subject: [PATCH 1/4] Fix for overly harsh checks when checking Merkle trees. --- sdk/src/assertions/bmff_hash.rs | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/sdk/src/assertions/bmff_hash.rs b/sdk/src/assertions/bmff_hash.rs index 2c1007c69..936fd9ba1 100644 --- a/sdk/src/assertions/bmff_hash.rs +++ b/sdk/src/assertions/bmff_hash.rs @@ -609,33 +609,13 @@ impl BmffHash { } }; - let sample_cnt = mp4.sample_count(mm.local_id).map_err(|_e| { - Error::InvalidAsset("Could not parse BMFF track sample".to_string()) - })?; - + let sample_cnt = track.sample_count(); if sample_cnt == 0 { return Err(Error::InvalidAsset("No samples".to_string())); } let track_id = track.track_id(); - // get the chunk count - let stbl_box = &track.trak.mdia.minf.stbl; - let chunk_cnt = match &stbl_box.stco { - Some(stco) => stco.entries.len(), - None => match &stbl_box.co64 { - Some(co64) => co64.entries.len(), - None => 0, - }, - }; - - // the Merkle count is the number of chunks for timed media - if mm.count != chunk_cnt as u32 { - return Err(Error::HashMismatch( - "Track count does not match Merkle map count".to_string(), - )); - } - // create sample to chunk mapping // create the Merkle tree per samples in a chunk let mut chunk_hash_map: HashMap = HashMap::new(); @@ -684,12 +664,6 @@ impl BmffHash { } } - if chunk_cnt != chunk_hash_map.len() { - return Err(Error::HashMismatch( - "Incorrect number of Merkle trees".to_string(), - )); - } - // finalize leaf hashes let mut leaf_hashes = Vec::new(); for chunk_bmff_mm in &track_to_bmff_merkle_map[&track_id] { From 3caa54d979176879f8e8205b994f1117b3e08c15 Mon Sep 17 00:00:00 2001 From: Maurice Fisher Date: Mon, 7 Aug 2023 11:04:11 -0400 Subject: [PATCH 2/4] Code simplification --- sdk/src/assertions/bmff_hash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/assertions/bmff_hash.rs b/sdk/src/assertions/bmff_hash.rs index 936fd9ba1..0f8255bd1 100644 --- a/sdk/src/assertions/bmff_hash.rs +++ b/sdk/src/assertions/bmff_hash.rs @@ -670,7 +670,7 @@ impl BmffHash { match chunk_hash_map.remove(&(chunk_bmff_mm.location + 1)) { Some(h) => { let h = Hasher::finalize(h); - leaf_hashes.push(h.clone()); + leaf_hashes.push(h); } None => { return Err(Error::HashMismatch( From 9fade77614ceb9b4e1d80184f996c3b0723e0253 Mon Sep 17 00:00:00 2001 From: Maurice Fisher Date: Thu, 10 Aug 2023 13:10:43 -0400 Subject: [PATCH 3/4] Fix missing id field from jumbf box reading. --- sdk/src/jumbf/boxes.rs | 95 +++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/sdk/src/jumbf/boxes.rs b/sdk/src/jumbf/boxes.rs index e694110e7..0b54f1e4a 100644 --- a/sdk/src/jumbf/boxes.rs +++ b/sdk/src/jumbf/boxes.rs @@ -30,6 +30,7 @@ use std::{ io::{Read, Result as IoResult, Seek, SeekFrom, Write}, }; +use byteorder::{BigEndian, ReadBytesExt}; use hex::FromHex; use log::debug; use thiserror::Error; @@ -1910,10 +1911,10 @@ impl BoxReader { reader.read_exact(&mut togs)?; bytes_left -= 1; + let mut sbuf = Vec::with_capacity(64); if togs[0] & 0x03 == 0x03 { // must be requestable and labeled // read label - let mut sbuf = Vec::with_capacity(64); loop { let mut buf = [0; 1]; reader.read_exact(&mut buf)?; @@ -1924,54 +1925,64 @@ impl BoxReader { sbuf.push(buf[0]); } } + } else { + return Err(JumbfParseError::InvalidDescriptionBox); + } - // if there is a signature, we need to read it... - let sig = if togs[0] & 0x08 == 0x08 { - let mut sigbuf: [u8; 32] = [0; 32]; - reader.read_exact(&mut sigbuf)?; - bytes_left -= 32; - Some(sigbuf) - } else { - None - }; - - // read private box if necessary - let private = if togs[0] & 0x10 == 0x10 { - let header = BoxReader::read_header(reader) - .map_err(|_| JumbfParseError::InvalidBoxHeader)?; - if header.size == 0 { - // bad read, - return Err(JumbfParseError::InvalidBoxHeader); - } else if header.size != bytes_left - HEADER_SIZE { - // this means that we started w/o the header... - unread_bytes(reader, HEADER_SIZE)?; - } + // box id + let bxid = if togs[0] & 0x04 == 0x04 { + let idbuf = reader.read_u32::()?; + bytes_left -= 4; + Some(idbuf) + } else { + None + }; + + // if there is a signature, we need to read it... + let sig = if togs[0] & 0x08 == 0x08 { + let mut sigbuf: [u8; 32] = [0; 32]; + reader.read_exact(&mut sigbuf)?; + bytes_left -= 32; + Some(sigbuf) + } else { + None + }; + + // read private box if necessary + let private = if togs[0] & 0x10 == 0x10 { + let header = + BoxReader::read_header(reader).map_err(|_| JumbfParseError::InvalidBoxHeader)?; + if header.size == 0 { + // bad read, + return Err(JumbfParseError::InvalidBoxHeader); + } else if header.size != bytes_left - HEADER_SIZE { + // this means that we started w/o the header... + unread_bytes(reader, HEADER_SIZE)?; + } - if header.name == BoxType::SaltHash { - let data_len = header.size - HEADER_SIZE; - let mut buf = vec![0u8; data_len as usize]; - reader.read_exact(&mut buf)?; + if header.name == BoxType::SaltHash { + let data_len = header.size - HEADER_SIZE; + let mut buf = vec![0u8; data_len as usize]; + reader.read_exact(&mut buf)?; - bytes_left -= header.size; + bytes_left -= header.size; - Some(CAISaltContentBox::new(buf)) - } else { - return Err(JumbfParseError::InvalidBoxHeader); - } + Some(CAISaltContentBox::new(buf)) } else { - None - }; - - if bytes_left != HEADER_SIZE { - // make sure we have consumed the entire box return Err(JumbfParseError::InvalidBoxHeader); } + } else { + None + }; - return Ok(JUMBFDescriptionBox::from( - &uuid, togs[0], sbuf, None, sig, private, - )); + if bytes_left != HEADER_SIZE { + // make sure we have consumed the entire box + return Err(JumbfParseError::InvalidBoxHeader); } - Err(JumbfParseError::InvalidDescriptionBox) + + return Ok(JUMBFDescriptionBox::from( + &uuid, togs[0], sbuf, bxid, sig, private, + )); } pub fn read_json_box( @@ -2192,6 +2203,7 @@ impl BoxReader { // load the description box & create a new superbox from it let jdesc = BoxReader::read_desc_box(reader, jumd_header.size) .map_err(|_| JumbfParseError::UnexpectedEof)?; + if jdesc.label().is_empty() { return Err(JumbfParseError::UnexpectedEof); } @@ -2213,8 +2225,7 @@ impl BoxReader { unread_bytes(reader, HEADER_SIZE)?; // seek back to the beginning of the box let next_box: Box = match box_header.name { BoxType::Jumb => Box::new( - BoxReader::read_super_box(reader) - .map_err(|_| JumbfParseError::InvalidJumbBox)?, + BoxReader::read_super_box(reader)?, //.map_err(|_| JumbfParseError::InvalidJumbBox)?, ), BoxType::Json => Box::new( BoxReader::read_json_box(reader, box_header.size) From 442f7730281a2f5fc165c743b71fbaa556200578 Mon Sep 17 00:00:00 2001 From: Maurice Fisher Date: Thu, 10 Aug 2023 13:22:49 -0400 Subject: [PATCH 4/4] clippy fixes --- sdk/src/jumbf/boxes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/jumbf/boxes.rs b/sdk/src/jumbf/boxes.rs index 0b54f1e4a..ea9c0368a 100644 --- a/sdk/src/jumbf/boxes.rs +++ b/sdk/src/jumbf/boxes.rs @@ -1980,9 +1980,9 @@ impl BoxReader { return Err(JumbfParseError::InvalidBoxHeader); } - return Ok(JUMBFDescriptionBox::from( + Ok(JUMBFDescriptionBox::from( &uuid, togs[0], sbuf, bxid, sig, private, - )); + )) } pub fn read_json_box(