Skip to content

Commit

Permalink
Use checked_add in utils/clap.rs
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 638824330
  • Loading branch information
vigneshvg authored and copybara-github committed May 30, 2024
1 parent 3c6f595 commit f56a6cc
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 100 deletions.
24 changes: 7 additions & 17 deletions src/decoder/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ impl Item {
return Err(AvifError::TruncatedData);
} else if self.extents.len() == 1 {
min_offset = sample.offset;
max_offset = sample.offset + u64_from_usize(sample.size)?;
max_offset = checked_add!(sample.offset, u64_from_usize(sample.size)?)?;
} else {
let mut remaining_size = sample.size;
for extent in &self.extents {
Expand All @@ -288,18 +288,14 @@ impl Item {
remaining_offset -= sizeu64;
continue;
} else {
start_offset = start_offset
.checked_add(remaining_offset)
.ok_or(AvifError::BmffParseFailed("bad extent".into()))?;
size -= usize_from_u64(remaining_offset)?;
checked_incr!(start_offset, remaining_offset);
checked_decr!(size, usize_from_u64(remaining_offset)?);
remaining_offset = 0;
}
}
// TODO(yguyon): Add comment to explain why it is fine to clip the extent size.
let used_extent_size = std::cmp::min(size, remaining_size);
let end_offset = start_offset
.checked_add(u64_from_usize(used_extent_size)?)
.ok_or(AvifError::BmffParseFailed("bad extent".into()))?;
let end_offset = checked_add!(start_offset, u64_from_usize(used_extent_size)?)?;
min_offset = std::cmp::min(min_offset, start_offset);
max_offset = std::cmp::max(max_offset, end_offset);
remaining_size -= used_extent_size;
Expand All @@ -313,7 +309,7 @@ impl Item {
}
Ok(Extent {
offset: min_offset,
size: usize_from_u64(max_offset - min_offset)?,
size: usize_from_u64(checked_sub!(max_offset, min_offset)?)?,
})
}
}
Expand Down Expand Up @@ -359,16 +355,10 @@ pub fn construct_items(meta: &MetaBox) -> AvifResult<Items> {
}
for extent in &iloc.extents {
item.extents.push(Extent {
offset: iloc
.base_offset
.checked_add(extent.offset)
.ok_or(AvifError::BmffParseFailed("".into()))?,
offset: checked_add!(iloc.base_offset, extent.offset)?,
size: extent.size,
});
item.size = item
.size
.checked_add(extent.size)
.ok_or(AvifError::BmffParseFailed("".into()))?;
checked_incr!(item.size, extent.size);
}
}
let mut ipma_seen: HashSet<u32> = HashSet::with_hasher(NonRandomHasherState);
Expand Down
65 changes: 33 additions & 32 deletions src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,11 @@ impl Extent {
if extent.size == 0 {
return Ok(());
}
let max_extent_1 = self
.offset
.checked_add(u64_from_usize(self.size)?)
.ok_or(AvifError::BmffParseFailed("".into()))?;
let max_extent_2 = extent
.offset
.checked_add(u64_from_usize(extent.size)?)
.ok_or(AvifError::BmffParseFailed("".into()))?;
let max_extent_1 = checked_add!(self.offset, u64_from_usize(self.size)?)?;
let max_extent_2 = checked_add!(extent.offset, u64_from_usize(extent.size)?)?;
self.offset = min(self.offset, extent.offset);
// The extents may not be contiguous. It does not matter for nth_image_max_extent().
self.size = usize_from_u64(max(max_extent_1, max_extent_2) - self.offset)?;
self.size = usize_from_u64(checked_sub!(max(max_extent_1, max_extent_2), self.offset)?)?;
Ok(())
}
}
Expand Down Expand Up @@ -619,7 +613,7 @@ impl Decoder {
if self.items.get(&item_id).unwrap().item_type != "grid" {
return Ok(());
}
let tile_count = self.tile_info[category.usize()].grid_tile_count() as usize;
let tile_count = self.tile_info[category.usize()].grid_tile_count()? as usize;
let mut grid_item_ids: Vec<u32> = create_vec_exact(tile_count)?;
#[allow(non_snake_case)]
let mut first_av1C: Option<CodecConfiguration> = None;
Expand Down Expand Up @@ -947,8 +941,12 @@ impl Decoder {
));
}
match tile.input.category {
Category::Color => self.io_stats.color_obu_size += sample.size,
Category::Alpha => self.io_stats.alpha_obu_size += sample.size,
Category::Color => {
checked_incr!(self.io_stats.color_obu_size, sample.size)
}
Category::Alpha => {
checked_incr!(self.io_stats.alpha_obu_size, sample.size)
}
_ => {}
}
}
Expand Down Expand Up @@ -1019,21 +1017,24 @@ impl Decoder {
}

#[allow(unreachable_code)]
fn can_use_single_codec(&self) -> bool {
fn can_use_single_codec(&self) -> AvifResult<bool> {
#[cfg(feature = "android_mediacodec")]
{
// Android MediaCodec does not support using a single codec instance for images of
// varying formats (which could happen when image contains alpha).
// TODO: return false for now. But investigate cases where it is possible to use a
// single codec instance (it may work for grids).
return false;
return Ok(false);
}
let total_tile_count = self.tiles[0].len() + self.tiles[1].len() + self.tiles[2].len();
let total_tile_count = checked_add!(
checked_add!(self.tiles[0].len(), self.tiles[1].len())?,
self.tiles[2].len()
)?;
if total_tile_count == 1 {
return true;
return Ok(true);
}
if self.image_count != 1 {
return false;
return Ok(false);
}
let mut image_buffers = 0;
let mut stolen_image_buffers = 0;
Expand All @@ -1047,18 +1048,18 @@ impl Decoder {
}
if stolen_image_buffers > 0 && image_buffers > 1 {
// Stealing will cause problems. So we need separate codec instances.
return false;
return Ok(false);
}
let operating_point = self.tiles[0][0].operating_point;
let all_layers = self.tiles[0][0].input.all_layers;
for tiles in &self.tiles {
for tile in tiles {
if tile.operating_point != operating_point || tile.input.all_layers != all_layers {
return false;
return Ok(false);
}
}
}
true
Ok(true)
}

fn create_codec(&mut self, operating_point: u8, all_layers: bool) -> AvifResult<()> {
Expand Down Expand Up @@ -1088,7 +1089,7 @@ impl Decoder {
)?;
self.tiles[1][0].codec_index = 1;
}
} else if self.can_use_single_codec() {
} else if self.can_use_single_codec()? {
self.codecs = create_vec_exact(1)?;
self.create_codec(
self.tiles[Category::Color.usize()][0].operating_point,
Expand Down Expand Up @@ -1153,9 +1154,7 @@ impl Decoder {
let mut bytes_to_skip = data.len(); // These extents were already merged.
for extent in &item.extents {
if bytes_to_skip != 0 {
bytes_to_skip = bytes_to_skip
.checked_sub(extent.size)
.ok_or(AvifError::BmffParseFailed("".into()))?;
checked_decr!(bytes_to_skip, extent.size);
continue;
}
let io = self.io.unwrap_mut();
Expand Down Expand Up @@ -1199,7 +1198,7 @@ impl Decoder {
};
let data = sample.data(io, item_data_buffer)?;
codec.get_next_image(data, sample.spatial_id, &mut tile.image, category)?;
self.tile_info[category.usize()].decoded_tile_count += 1;
checked_incr!(self.tile_info[category.usize()].decoded_tile_count, 1);

if category == Category::Alpha && tile.image.yuv_range == YuvRange::Limited {
tile.image.alpha_to_full_range()?;
Expand All @@ -1210,15 +1209,15 @@ impl Decoder {
if tile_index == 0 {
// Validate the grid image size
let grid = &self.tile_info[category.usize()].grid;
if tile.image.width * grid.columns < grid.width
|| tile.image.height * grid.rows < grid.height
if checked_mul!(tile.image.width, grid.columns)? < grid.width
|| checked_mul!(tile.image.height, grid.rows)? < grid.height
{
return Err(AvifError::InvalidImageGrid(
"Grid image tiles do not completely cover the image (HEIF (ISO/IEC 23008-12:2017), Section 6.6.2.3.1)".into(),
));
}
if tile.image.width * (grid.columns - 1) >= grid.width
|| tile.image.height * (grid.rows - 1) >= grid.height
if checked_mul!(tile.image.width, grid.columns - 1)? >= grid.width
|| checked_mul!(tile.image.height, grid.rows - 1)? >= grid.height
{
return Err(AvifError::InvalidImageGrid(
"Grid image tiles in the rightmost column and bottommost row do not overlap the reconstructed image grid canvas. See MIAF (ISO/IEC 23000-22:2019), Section 7.3.11.4.2, Figure 2".into(),
Expand Down Expand Up @@ -1337,7 +1336,7 @@ impl Decoder {
}
}

let next_image_index = self.image_index + 1;
let next_image_index = checked_add!(self.image_index, 1)?;
self.create_codecs()?;
self.prepare_samples(next_image_index as usize)?;
self.decode_tiles(next_image_index as usize)?;
Expand Down Expand Up @@ -1366,15 +1365,17 @@ impl Decoder {
return Err(AvifError::NoImagesRemaining);
}
let requested_index = i32_from_u32(index)?;
if requested_index == (self.image_index + 1) {
if requested_index == checked_add!(self.image_index, 1)? {
return self.next_image();
}
if requested_index == self.image_index && self.is_current_frame_fully_decoded() {
// Current frame which is already fully decoded has been requested. Do nothing.
return Ok(());
}
let nearest_keyframe = i32_from_u32(self.nearest_keyframe(index))?;
if nearest_keyframe > (self.image_index + 1) || requested_index <= self.image_index {
if nearest_keyframe > checked_add!(self.image_index, 1)?
|| requested_index <= self.image_index
{
// Start decoding from the nearest keyframe.
self.image_index = nearest_keyframe - 1;
}
Expand Down
33 changes: 12 additions & 21 deletions src/decoder/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl DecodeSample {
match buffer {
Some(x) => {
let start_offset = usize_from_u64(self.offset)?;
let end_offset = start_offset + size;
let end_offset = checked_add!(start_offset, size)?;
let range = start_offset..end_offset;
check_slice_range(x.len(), &range)?;
Ok(&x[range])
Expand Down Expand Up @@ -74,11 +74,11 @@ impl TileInfo {
self.grid.rows > 0 && self.grid.columns > 0
}

pub fn grid_tile_count(&self) -> u32 {
pub fn grid_tile_count(&self) -> AvifResult<u32> {
if self.is_grid() {
self.grid.rows * self.grid.columns
checked_mul!(self.grid.rows, self.grid.columns)
} else {
1
Ok(1)
}
}

Expand Down Expand Up @@ -187,11 +187,9 @@ impl Tile {
"lsel layer index not found in a1lx.".into(),
));
}
let layer_id_plus_1 = layer_id
.checked_add(1)
.ok_or(AvifError::BmffParseFailed("".into()))?;
let layer_id_plus_1 = layer_id + 1;
for layer_size in layer_sizes.iter().take(layer_id_plus_1) {
sample_size += layer_size;
checked_incr!(sample_size, *layer_size);
}
} else {
// This layer payload subsection is not known. Use the whole payload.
Expand All @@ -218,13 +216,13 @@ impl Tile {
for (i, layer_size) in layer_sizes.iter().take(layer_count).enumerate() {
let sample = DecodeSample {
item_id: item.id,
offset: base_item_offset + offset,
offset: checked_add!(base_item_offset, offset)?,
size: *layer_size,
spatial_id: 0xff,
sync: i == 0, // Assume all layers depend on the first layer.
};
tile.input.samples.push(sample);
offset += *layer_size as u64;
offset = checked_add!(offset, *layer_size as u64)?;
}
} else {
// Typical case: Use the entire item's payload for a single frame output
Expand Down Expand Up @@ -291,13 +289,8 @@ impl Tile {
let mut sample_offset = *chunk_offset;
for _ in 0..sample_count {
let sample_size = sample_table.sample_size(sample_size_index)?;
let sample_size_hint = sample_offset.checked_add(sample_size as u64);
if sample_size_hint.is_none() {
return Err(AvifError::BmffParseFailed(
"overflow in sample offset+size".into(),
));
}
if size_hint != 0 && sample_size_hint.unwrap() > size_hint {
let sample_size_hint = checked_add!(sample_offset, sample_size as u64)?;
if size_hint != 0 && sample_size_hint > size_hint {
return Err(AvifError::BmffParseFailed("exceeded size_hint".into()));
}
let sample = DecodeSample {
Expand All @@ -311,10 +304,8 @@ impl Tile {
sync: tile.input.samples.is_empty(),
};
tile.input.samples.push(sample);
sample_offset = sample_offset
.checked_add(sample_size as u64)
.ok_or(AvifError::BmffParseFailed("".into()))?;
sample_size_index += 1;
checked_incr!(sample_offset, sample_size as u64);
checked_incr!(sample_size_index, 1);
}
}
for sync_sample_number in &sample_table.sync_samples {
Expand Down
23 changes: 12 additions & 11 deletions src/decoder/track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@ impl Track {
"invalid track duration 0".into(),
));
}
let remainder =
if self.track_duration % self.segment_duration != 0 { 1u64 } else { 0u64 };
let repetition_count: u64 =
(self.track_duration / self.segment_duration) + remainder - 1u64;
let repetition_count: u64 = self.track_duration.div_ceil(self.segment_duration) - 1;
return match i32::try_from(repetition_count) {
Ok(value) => Ok(RepetitionCount::Finite(value)),
Err(_) => Ok(RepetitionCount::Infinite),
Expand All @@ -101,9 +98,13 @@ impl Track {
..ImageTiming::default()
};
for i in 0..image_index as usize {
image_timing.pts_in_timescales += sample_table.image_delta(i) as u64;
checked_incr!(
image_timing.pts_in_timescales,
sample_table.image_delta(i)? as u64
);
}
image_timing.duration_in_timescales = sample_table.image_delta(image_index as usize) as u64;
image_timing.duration_in_timescales =
sample_table.image_delta(image_index as usize)? as u64;
if image_timing.timescale > 0 {
image_timing.pts =
image_timing.pts_in_timescales as f64 / image_timing.timescale as f64;
Expand Down Expand Up @@ -198,15 +199,15 @@ impl SampleTable {
})
}

pub fn image_delta(&self, index: usize) -> u32 {
let mut max_index = 0;
pub fn image_delta(&self, index: usize) -> AvifResult<u32> {
let mut max_index: u32 = 0;
for (i, time_to_sample) in self.time_to_sample.iter().enumerate() {
max_index += time_to_sample.sample_count;
checked_incr!(max_index, time_to_sample.sample_count);
if index < max_index as usize || i == self.time_to_sample.len() - 1 {
return time_to_sample.sample_delta;
return Ok(time_to_sample.sample_delta);
}
}
1
Ok(1)
}
}

Expand Down
Loading

0 comments on commit f56a6cc

Please sign in to comment.