Skip to content

Commit

Permalink
fix: Fix #624 (edge cases when combining the box hashes) (#625)
Browse files Browse the repository at this point in the history
  • Loading branch information
brogdonm authored Nov 15, 2024
1 parent ce1d533 commit aab027a
Showing 1 changed file with 168 additions and 1 deletion.
169 changes: 168 additions & 1 deletion sdk/src/assertions/box_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,22 @@ impl BoxHash {
}
}

self.boxes = vec![before_c2pa, c2pa_box, after_c2pa];
// Instead of assuming we can combine all of the different ranges of
// box hashes, we will check the bounds of each one
let mut boxes = Vec::<BoxMap>::new();
// Only add if we have some before the C2PA box
if before_c2pa.range_len > 0 {
boxes.push(before_c2pa);
}
// Do the same for the actual C2PA box
if c2pa_box.range_len > 0 {
boxes.push(c2pa_box);
}
// And finally, add the boxes after the C2PA box
if after_c2pa.range_len > 0 {
boxes.push(after_c2pa);
}
self.boxes = boxes;

// compute the hashes
for bm in self.boxes.iter_mut() {
Expand Down Expand Up @@ -457,4 +472,156 @@ mod tests {
.verify_stream_hash(&mut input, Some("sha256"), bhp)
.unwrap();
}

// Setup a mock for the AssetBoxHash trait
mockall::mock! {
pub MABH { }
impl AssetBoxHash for MABH {
fn get_box_map(&self, reader: &mut dyn CAIRead) -> Result<Vec<BoxMap>>;
}
}

#[test]
fn test_with_no_box_hashes_after_c2pa() {
// Algorithm to use
let alg = "sha256";
// Create a mock object
let mut mock = MockMABH::new();
// Setup the expectation when asked for the box map
mock.expect_get_box_map().returning(|_| {
Ok(vec![
// Make sure the first one is the C2PA box
BoxMap {
names: vec!["C2PA".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 0,
range_len: 10,
},
// And follow with
BoxMap {
names: vec!["test".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 10,
range_len: 10,
},
])
});
// The data size must match what we return in the expectation
let data = vec![0u8; 20];
// And create a reader on that data, for the API call
let mut reader = Cursor::new(data);
// Create the BoxHash object
let mut bh = BoxHash { boxes: Vec::new() };
// And generate the box hashes
let result = bh.generate_box_hash_from_stream(&mut reader, alg, &mock, true);
// We should expect an OK result
assert!(result.is_ok());
// With a total of 2 boxes
assert_eq!(bh.boxes.len(), 2);
assert_eq!(bh.boxes[0].names[0], "C2PA");
assert_eq!(bh.boxes[1].names[0], "test");
}

#[test]
fn test_with_no_box_hashes_before_c2pa() {
// Algorithm to use
let alg = "sha256";
// Create a mock object
let mut mock = MockMABH::new();
// Setup the expectation when asked for the box map
mock.expect_get_box_map().returning(|_| {
Ok(vec![
// And follow with
BoxMap {
names: vec!["test".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 0,
range_len: 10,
},
// Make sure the first one is the C2PA box
BoxMap {
names: vec!["C2PA".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 10,
range_len: 10,
},
])
});
// The data size must match what we return in the expectation
let data = vec![0u8; 20];
// And create a reader on that data, for the API call
let mut reader = Cursor::new(data);
// Create the BoxHash object
let mut bh = BoxHash { boxes: Vec::new() };
// And generate the box hashes
let result = bh.generate_box_hash_from_stream(&mut reader, alg, &mock, true);
// We should expect an OK result
assert!(result.is_ok());
// With a total of 2 boxes
assert_eq!(bh.boxes.len(), 2);
assert_eq!(bh.boxes[0].names[0], "test");
assert_eq!(bh.boxes[1].names[0], "C2PA");
}

#[test]
fn test_with_no_box_hashes_before_and_after_c2pa() {
// Algorithm to use
let alg = "sha256";
// Create a mock object
let mut mock = MockMABH::new();
// Setup the expectation when asked for the box map
mock.expect_get_box_map().returning(|_| {
Ok(vec![
// And follow with
BoxMap {
names: vec!["test".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 0,
range_len: 10,
},
// Make sure the first one is the C2PA box
BoxMap {
names: vec!["C2PA".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 10,
range_len: 10,
},
BoxMap {
names: vec!["test1".to_string()],
alg: Some(alg.to_string()),
hash: ByteBuf::from(vec![0]),
pad: ByteBuf::from(vec![]),
range_start: 20,
range_len: 10,
},
])
});
// The data size must match what we return in the expectation
let data = vec![0u8; 30];
// And create a reader on that data, for the API call
let mut reader = Cursor::new(data);
// Create the BoxHash object
let mut bh = BoxHash { boxes: Vec::new() };
// And generate the box hashes
let result = bh.generate_box_hash_from_stream(&mut reader, alg, &mock, true);
// We should expect an OK result
assert!(result.is_ok());
// With a total of 2 boxes
assert_eq!(bh.boxes.len(), 3);
assert_eq!(bh.boxes[0].names[0], "test");
assert_eq!(bh.boxes[1].names[0], "C2PA");
assert_eq!(bh.boxes[2].names[0], "test1");
}
}

0 comments on commit aab027a

Please sign in to comment.