Bug 1967030 - Update mp4parse-rust to d3e4d255. r=media-playback-reviewers,supply-chain-reviewers,padenot

Differential Revision: https://phabricator.services.mozilla.com/D249858
This commit is contained in:
Matthew Gregan
2025-05-20 20:40:33 +00:00
committed by mgregan@mozilla.com
parent 251a73199e
commit 0888571e1e
23 changed files with 312 additions and 337 deletions

View File

@@ -95,9 +95,9 @@ git = "https://github.com/mozilla/midir.git"
rev = "85156e360a37d851734118104619f86bd18e94c6" rev = "85156e360a37d851734118104619f86bd18e94c6"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b"] [source."git+https://github.com/mozilla/mp4parse-rust?rev=d3e4d255bd149d341c7e90f5e9fc84e743a8e179"]
git = "https://github.com/mozilla/mp4parse-rust" git = "https://github.com/mozilla/mp4parse-rust"
rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b" rev = "d3e4d255bd149d341c7e90f5e9fc84e743a8e179"
replace-with = "vendored-sources" replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/neqo?tag=v0.13.2"] [source."git+https://github.com/mozilla/neqo?tag=v0.13.2"]

11
Cargo.lock generated
View File

@@ -1984,11 +1984,11 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]] [[package]]
name = "fallible_collections" name = "fallible_collections"
version = "0.4.9" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" checksum = "8b3e85d14d419ba3e1db925519461c0d17a49bdd2d67ea6316fa965ca7acdf74"
dependencies = [ dependencies = [
"hashbrown 0.13.999", "hashbrown 0.14.999",
] ]
[[package]] [[package]]
@@ -2573,7 +2573,6 @@ dependencies = [
"dom_fragmentdirectives", "dom_fragmentdirectives",
"encoding_glue", "encoding_glue",
"etagere", "etagere",
"fallible_collections",
"fluent", "fluent",
"fluent-fallback", "fluent-fallback",
"fluent-ffi", "fluent-ffi",
@@ -4604,7 +4603,7 @@ dependencies = [
[[package]] [[package]]
name = "mp4parse" name = "mp4parse"
version = "0.17.0" version = "0.17.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b#e64650a686e5c5732395cd059e17cfd3b1e5b63b" source = "git+https://github.com/mozilla/mp4parse-rust?rev=d3e4d255bd149d341c7e90f5e9fc84e743a8e179#d3e4d255bd149d341c7e90f5e9fc84e743a8e179"
dependencies = [ dependencies = [
"bitreader", "bitreader",
"byteorder", "byteorder",
@@ -4621,7 +4620,7 @@ version = "0.1.0"
[[package]] [[package]]
name = "mp4parse_capi" name = "mp4parse_capi"
version = "0.17.0" version = "0.17.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=e64650a686e5c5732395cd059e17cfd3b1e5b63b#e64650a686e5c5732395cd059e17cfd3b1e5b63b" source = "git+https://github.com/mozilla/mp4parse-rust?rev=d3e4d255bd149d341c7e90f5e9fc84e743a8e179#d3e4d255bd149d341c7e90f5e9fc84e743a8e179"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"fallible_collections", "fallible_collections",

View File

@@ -2178,6 +2178,12 @@ criteria = "safe-to-deploy"
delta = "0.4.6 -> 0.4.9" delta = "0.4.6 -> 0.4.9"
notes = "Mostly soundness fixes." notes = "Mostly soundness fixes."
[[audits.fallible_collections]]
who = "Matthew Gregan <kinetik@flim.org>"
criteria = "safe-to-deploy"
delta = "0.4.9 -> 0.5.1"
notes = "Changes are largely removal of Rust < 1.57 support and dependency updates."
[[audits.fastrand]] [[audits.fastrand]]
who = "Mike Hommey <mh+mozilla@glandium.org>" who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy" criteria = "safe-to-deploy"

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"050bb460a70e6ddd572fdf118e5d52ae8dc1c7801af6475ef2ab9dfd34d963ab","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"63b0c7dac05e6dfba32dcd4cb8e671bb8b72525f67a6b17fa5b8f10fd2cab047","src/arc.rs":"fda02f28d359193cbc0ec988b7c8149e9212c1951dff9cba6041a9ebd7fa3f17","src/boxed.rs":"8d7b3afc19e27ca51a843490d346319807cfdcc268355272c3164756fd63c242","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"557ce3ff2d02c425adcb2b4ac53b6b6607c25c535aee8ffa4f12bf773fbcd763","src/btree/node.rs":"49feca8742513b1c29d2f949c1eb1b178b538097ae94ba9dc31b8323a6423ea6","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"607f0db0b189c39b41824fbbf6fd8d9c5fdf85cc40f4437b13152e7b86d2979f","src/format.rs":"5142970f6ac1fe66f667ee2565af786802e93e6728ec3a1b82ffaa9f6a6b5bce","src/hashmap.rs":"1b9bf03fd2f2d9412ea2dad6963e1d37d51662e7091424bfcdc44a502f4e64bc","src/lib.rs":"71c5dc986ad58a4515604a73a4b7f4d8b6f43d2831993ee8612c99978ff2bb42","src/rc.rs":"f327a0adcfd2b1e225913ae716deb96777ca562985ac64e3b83550111f809864","src/try_clone.rs":"725130e0ddacde1ff7c976de62fbe45d01c67412af395aa41cac4bcfb85f6a5f","src/try_reserve_error.rs":"5e8db6a538225e66fec5d9d3a4314939b5b0428180676eb55ab928875e4feefd","src/vec.rs":"4268ae1de90750c21503fc84bdbf46cd6ccf76e33ae7f7daf8050fb29b839db1"},"package":"a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd"} {"files":{"Cargo.toml":"70a708a66e4364764d00147d8e4f7189b3b95e1ff712f59fbe17a74f28409c46","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"edbf4f0c8ab2b2eeec5f167205a3b70261a3f19f3426c21aead9011cc217ecdb","rustfmt.toml":"b52c3059df95b63e647dd5f7730ca032786486041775017e96f083b3ae464372","src/arc.rs":"d9a2a788166da905df2efba1106055fd35001c34f2d1baa460f81440a077c669","src/boxed.rs":"0e521e1c62d16cdcbf8ce955ab94667613b7ba508920ec89ed7f1048abe63f65","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"557ce3ff2d02c425adcb2b4ac53b6b6607c25c535aee8ffa4f12bf773fbcd763","src/btree/node.rs":"49feca8742513b1c29d2f949c1eb1b178b538097ae94ba9dc31b8323a6423ea6","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"607f0db0b189c39b41824fbbf6fd8d9c5fdf85cc40f4437b13152e7b86d2979f","src/format.rs":"5142970f6ac1fe66f667ee2565af786802e93e6728ec3a1b82ffaa9f6a6b5bce","src/hashmap.rs":"3c8eb3aa44fe588bc81f1726add4e35332822878203cd8c48b407bf87bef59d6","src/lib.rs":"e9f574c61012d379fda211e66da25a871186095fba94fb4b1765945d79380495","src/rc.rs":"a4c53d6e5a2b8230c79aed456cb574e839ce2d6c42ee08491bc0a824c8437fe4","src/try_clone.rs":"725130e0ddacde1ff7c976de62fbe45d01c67412af395aa41cac4bcfb85f6a5f","src/vec.rs":"0a09c7350681d9ff41d03c8ff8c26c437c311312ce9effc3eb6eb47c835c93d3"},"package":"8b3e85d14d419ba3e1db925519461c0d17a49bdd2d67ea6316fa965ca7acdf74"}

View File

@@ -10,26 +10,43 @@
# See Cargo.toml.orig for the original contents. # See Cargo.toml.orig for the original contents.
[package] [package]
edition = "2018" edition = "2021"
rust-version = "1.64"
name = "fallible_collections" name = "fallible_collections"
version = "0.4.9" version = "0.5.1"
authors = ["vcombey <vcombey@student.42.fr>"] authors = ["vcombey <vcombey@student.42.fr>"]
build = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "a crate which adds fallible allocation api to std collections" description = "a crate which adds fallible allocation api to std collections"
readme = "README.md" readme = "README.md"
keywords = [ keywords = [
"fallible", "fallible",
"allocation",
"collections", "collections",
"oom",
"try-reserve",
] ]
license = "MIT/Apache-2.0" categories = [
"rust-patterns",
"memory-management",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/vcombey/fallible_collections.git" repository = "https://github.com/vcombey/fallible_collections.git"
[lib]
name = "fallible_collections"
path = "src/lib.rs"
[dependencies.hashbrown] [dependencies.hashbrown]
version = "0.13" version = "0.14"
optional = true optional = true
[features] [features]
default = ["hashmap"] default = ["hashmap"]
hashmap = ["hashbrown"] hashmap = ["dep:hashbrown"]
rust_1_57 = [] rust_1_57 = []
std = [] std = []
std_io = ["std"] std_io = ["std"]

View File

@@ -1,38 +1,34 @@
Fallible Collections.rs Fallible Collections.rs
============== ==============
Implement api on rust collection wich returns a result when an allocation error occurs. Implements APIs on Rust collections wich gracefully return a `Result` when an allocation error occurs.
This is inspired a lot by [RFC 2116](https://github.com/rust-lang/rfcs/blob/master/text/2116-alloc-me-maybe.md). This is inspired a lot by [RFC 2116](https://github.com/rust-lang/rfcs/blob/master/text/2116-alloc-me-maybe.md).
The api currently propose a fallible interface for Vec, Box, Arc, Btree and Rc, There are APIs for a fallible interface for `Vec`, `Box`, `BTree`, `HashMap`,
a TryClone trait wich is implemented for primitive rust traits and a fallible format macro. and a `TryClone` trait wich is implemented for primitive Rust traits and a fallible format macro.
You can use this with `try_clone_derive` crate wich derive `TryClone` for your own types.
You can use this with try_clone_derive crate wich derive TryClone for your own types.
# Getting Started # Getting Started
[fallible collections is available on crates.io](https://crates.io/crates/fallible_collections). [`fallible_collections` is available on crates.io](https://crates.io/crates/fallible_collections).
It is recommended to look there for the newest released version, as well as links to the newest builds of the docs. It is recommended to look there for the newest released version, as well as links to the newest builds of the docs.
At the point of the last update of this README, the latest published version could be used like this: Add the following dependency to your Cargo manifest:
Add the following dependency to your Cargo manifest...
Add feature std and rust_1_57 to use the stabilized try_reserve api and the std HashMap type. Obviously, you cannot combine it with the 'unstable' feature.
Add integration tests that can be run with the tiny_integration_tester command.
```toml ```toml
[dependencies] [dependencies]
fallible_collections = "0.4" fallible_collections = "0.5"
# or # or
fallible_collections = { version = "0.4", features = ["std", "rust_1_57"] } fallible_collections = { version = "0.5", features = ["std"] }
``` ```
...and see the [docs](https://docs.rs/fallible_collections) for how to use it. ...and see the [docs](https://docs.rs/fallible_collections) for how to use it.
# Example # Example
Exemple of using the FallibleBox interface. Exemple of using the `FallibleBox` interface.
```rust ```rust
use fallible_collections::FallibleBox; use fallible_collections::FallibleBox;
@@ -47,7 +43,8 @@ fn main() {
} }
``` ```
Exemple of using the FallibleVec interface. Exemple of using the `FallibleVec` interface.
```rust ```rust
use fallible_collections::FallibleVec; use fallible_collections::FallibleVec;

View File

@@ -0,0 +1,3 @@
# Basic formatting options
edition = "2018"

View File

@@ -1,16 +1,16 @@
//! Implement a Fallible Arc //! Implement a Fallible Arc
#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))] #[cfg(not(feature = "unstable"))]
use super::FallibleBox; use super::FallibleBox;
use super::TryClone; use super::TryClone;
use crate::TryReserveError; use crate::TryReserveError;
#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))] #[cfg(not(feature = "unstable"))]
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::sync::Arc; use alloc::sync::Arc;
/// trait to implement Fallible Arc /// trait to implement Fallible Arc
#[cfg_attr( #[cfg_attr(
any(not(feature = "unstable"), feature = "rust_1_57"), not(feature = "unstable"),
deprecated( deprecated(
since = "0.3.1", since = "0.3.1",
note = "this function is not completely fallible, it can panic !, see [issue](https://github.com/vcombey/fallible_collections/issues/13). help wanted" note = "this function is not completely fallible, it can panic !, see [issue](https://github.com/vcombey/fallible_collections/issues/13). help wanted"
@@ -27,13 +27,13 @@ pub trait FallibleArc<T> {
#[allow(deprecated)] #[allow(deprecated)]
impl<T> FallibleArc<T> for Arc<T> { impl<T> FallibleArc<T> for Arc<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> { fn try_new(t: T) -> Result<Self, TryReserveError> {
#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))] #[cfg(not(feature = "unstable"))]
{ {
// doesn't work as the inner variable of arc are also stocked in the box // doesn't work as the inner variable of arc are also stocked in the box
let b = <Box<T> as FallibleBox<T>>::try_new(t)?; let b = <Box<T> as FallibleBox<T>>::try_new(t)?;
Ok(Arc::from(b)) Ok(Arc::from(b))
} }
#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))] #[cfg(feature = "unstable")]
{ {
use alloc::alloc::Layout; use alloc::alloc::Layout;
use alloc::collections::TryReserveErrorKind; use alloc::collections::TryReserveErrorKind;

View File

@@ -1,11 +1,10 @@
//! Implement Fallible Box //! Implement Fallible Box
use super::TryClone; use super::TryClone;
use crate::TryReserveError; use crate::TryReserveError;
use alloc::alloc::Layout;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::borrow::Borrow; use core::borrow::Borrow;
use core::mem::ManuallyDrop;
use core::ops::Deref; use core::ops::Deref;
use core::ptr::NonNull;
/// trait to implement Fallible Box /// trait to implement Fallible Box
pub trait FallibleBox<T> { pub trait FallibleBox<T> {
@@ -63,47 +62,15 @@ impl<T> Deref for TryBox<T> {
} }
} }
fn alloc(layout: Layout) -> Result<NonNull<u8>, TryReserveError> {
#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))] // requires allocator_api
{
use alloc::collections::TryReserveErrorKind;
use core::alloc::Allocator;
alloc::alloc::Global
.allocate(layout)
.map_err(|_e| {
TryReserveErrorKind::AllocError {
layout,
non_exhaustive: (),
}
.into()
})
.map(|v| v.cast())
}
#[cfg(any(not(feature = "unstable"), feature = "rust_1_57"))]
{
match layout.size() {
0 => {
// Required for alloc safety
// See https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#safety-1
Ok(NonNull::dangling())
}
1..=core::usize::MAX => {
let ptr = unsafe { alloc::alloc::alloc(layout) };
core::ptr::NonNull::new(ptr).ok_or(TryReserveError::AllocError { layout })
}
_ => unreachable!("size must be non-negative"),
}
}
}
impl<T> FallibleBox<T> for Box<T> { impl<T> FallibleBox<T> for Box<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> { fn try_new(t: T) -> Result<Self, TryReserveError> {
let layout = Layout::for_value(&t); let mut vec = alloc::vec::Vec::new();
let ptr = alloc(layout)?.as_ptr() as *mut T; vec.try_reserve_exact(1)?;
unsafe { vec.push(t);
core::ptr::write(ptr, t); // try_reserve_exact doesn't promise the exact size, but into_boxed_slice does.
Ok(Box::from_raw(ptr)) // in practice the size is going to be okay anyway, so it won't realloc.
} let ptr: *mut T = ManuallyDrop::new(vec.into_boxed_slice()).as_mut_ptr();
Ok(unsafe { Box::from_raw(ptr) })
} }
} }

View File

@@ -6,17 +6,17 @@ use core::default::Default;
use core::fmt::Debug; use core::fmt::Debug;
use core::hash::Hash; use core::hash::Hash;
#[cfg(not(all(feature = "std", feature = "rust_1_57")))] #[cfg(not(feature = "std"))]
type HashMap<K, V> = hashbrown::hash_map::HashMap<K, V>; type HashMap<K, V> = hashbrown::hash_map::HashMap<K, V>;
#[cfg(all(feature = "std", feature = "rust_1_57"))] #[cfg(feature = "std")]
type HashMap<K, V> = std::collections::HashMap<K, V>; type HashMap<K, V> = std::collections::HashMap<K, V>;
#[cfg(not(all(feature = "std", feature = "rust_1_57")))] #[cfg(not(feature = "std"))]
use hashbrown::hash_map::{Iter, IntoIter}; use hashbrown::hash_map::{IntoIter, Iter};
#[cfg(all(feature = "std", feature = "rust_1_57"))] #[cfg(feature = "std")]
use std::collections::hash_map::{Iter, IntoIter}; use std::collections::hash_map::{IntoIter, Iter};
pub struct TryHashMap<K, V> { pub struct TryHashMap<K, V> {
inner: HashMap<K, V>, inner: HashMap<K, V>,
@@ -87,20 +87,9 @@ where
#[inline(always)] #[inline(always)]
fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
#[cfg(not(all(feature = "std", feature = "rust_1_57")))] self.inner
{ .try_reserve(additional)
self.inner.try_reserve(additional) .map_err(|_| make_try_reserve_error())
}
#[cfg(all(feature = "std", feature = "rust_1_57"))]
{
self.inner.try_reserve(additional).map_err(|_| {
crate::make_try_reserve_error(self.len(), additional,
core::mem::size_of::<K>() + core::mem::size_of::<V>(),
core::mem::align_of::<K>().max(core::mem::align_of::<V>()),
)
})
}
} }
} }
@@ -137,3 +126,10 @@ fn tryhashmap_oom() {
_ => (), _ => (),
} }
} }
#[cold]
fn make_try_reserve_error() -> TryReserveError {
let mut v: alloc::vec::Vec<[u8; 1024]> = alloc::vec::Vec::new();
// this will always overflow capacity
v.try_reserve(!0).unwrap_err()
}

View File

@@ -31,13 +31,6 @@
#![cfg_attr(feature = "unstable", feature(maybe_uninit_slice))] #![cfg_attr(feature = "unstable", feature(maybe_uninit_slice))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_uninit_array))] #![cfg_attr(feature = "unstable", feature(maybe_uninit_uninit_array))]
#[cfg(all(feature = "unstable", feature = "rust_1_57"))]
compile_error!(
"The use of the 'unstable' feature combined with the \
'rust_1_57' feature, which is related to the partial stabilization \
of the allocator API since rustc version 1.57, does not make sense!"
);
extern crate alloc; extern crate alloc;
#[cfg(feature = "std")] #[cfg(feature = "std")]
extern crate std; extern crate std;
@@ -49,7 +42,9 @@ pub mod vec;
pub use vec::*; pub use vec::*;
pub mod rc; pub mod rc;
pub use rc::*; pub use rc::*;
#[cfg(target_has_atomic = "ptr")]
pub mod arc; pub mod arc;
#[cfg(target_has_atomic = "ptr")]
pub use arc::*; pub use arc::*;
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub mod btree; pub mod btree;
@@ -61,8 +56,7 @@ pub use hashmap::*;
pub mod format; pub mod format;
pub mod try_clone; pub mod try_clone;
pub mod try_reserve_error; pub use alloc::collections::TryReserveError;
pub use try_reserve_error::TryReserveError;
#[cfg(feature = "std_io")] #[cfg(feature = "std_io")]
pub use vec::std_io::*; pub use vec::std_io::*;
@@ -83,13 +77,3 @@ pub trait TryClone {
where where
Self: core::marker::Sized; Self: core::marker::Sized;
} }
#[cfg(feature = "rust_1_57")]
fn make_try_reserve_error(len: usize, additional: usize, elem_size: usize, align: usize) -> TryReserveError {
if let Some(size) = len.checked_add(additional).and_then(|l| l.checked_mul(elem_size)) {
if let Ok(layout) = alloc::alloc::Layout::from_size_align(size, align) {
return TryReserveError::AllocError { layout }
}
}
TryReserveError::CapacityOverflow
}

View File

@@ -3,7 +3,15 @@ use super::FallibleBox;
use crate::TryReserveError; use crate::TryReserveError;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::rc::Rc; use alloc::rc::Rc;
/// trait to implement Fallible Rc /// trait to implement Fallible Rc
#[cfg_attr(
any(not(feature = "unstable"), feature = "rust_1_57"),
deprecated(
since = "0.4.9",
note = "this function is not completely fallible, it can panic!, see [issue](https://github.com/vcombey/fallible_collections/issues/13). help wanted"
)
)]
pub trait FallibleRc<T> { pub trait FallibleRc<T> {
/// try creating a new Rc, returning a Result<Box<T>, /// try creating a new Rc, returning a Result<Box<T>,
/// TryReserveError> if allocation failed /// TryReserveError> if allocation failed
@@ -12,6 +20,7 @@ pub trait FallibleRc<T> {
Self: Sized; Self: Sized;
} }
#[allow(deprecated)]
impl<T> FallibleRc<T> for Rc<T> { impl<T> FallibleRc<T> for Rc<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> { fn try_new(t: T) -> Result<Self, TryReserveError> {
let b = <Box<T> as FallibleBox<T>>::try_new(t)?; let b = <Box<T> as FallibleBox<T>>::try_new(t)?;

View File

@@ -1,19 +0,0 @@
#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))]
pub use alloc::collections::TryReserveError;
#[cfg(all(feature = "hashmap", not(all(feature = "unstable", not(feature = "rust_1_57")))))]
pub use hashbrown::TryReserveError;
/// The error type for `try_reserve` methods.
#[cfg(all(not(feature = "hashmap"), not(all(feature = "unstable", not(feature = "rust_1_57")))))]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TryReserveError {
/// Error due to the computed capacity exceeding the collection's maximum
/// (usually `isize::MAX` bytes).
CapacityOverflow,
/// The memory allocator returned an error
AllocError {
/// The layout of the allocation request that failed.
layout: alloc::alloc::Layout,
},
}

View File

@@ -431,108 +431,22 @@ impl<'a, T> Iterator for IterMut<'a, T> {
} }
} }
/// Grow capacity exponentially
#[cold]
fn vec_try_reserve_for_growth<T>(v: &mut Vec<T>, additional: usize) -> Result<(), TryReserveError> {
// saturating, because can't use CapacityOverflow here if rust_1_57 flag is enabled
FallibleVec::try_reserve(v, additional.max(v.capacity().saturating_mul(2) - v.len()))
}
fn needs_to_grow<T>(v: &Vec<T>, len: usize) -> bool { fn needs_to_grow<T>(v: &Vec<T>, len: usize) -> bool {
v.len().checked_add(len).map_or(true, |needed| needed > v.capacity()) v.len()
} .checked_add(len)
.map_or(true, |needed| needed > v.capacity())
#[cfg(not(any(feature = "unstable", feature = "rust_1_57")))]
fn vec_try_reserve<T>(v: &mut Vec<T>, additional: usize) -> Result<(), TryReserveError> {
let available = v.capacity().checked_sub(v.len()).expect("capacity >= len");
if additional > available {
let increase = additional
.checked_sub(available)
.expect("additional > available");
let new_cap = v
.capacity()
.checked_add(increase)
.ok_or(TryReserveError::CapacityOverflow)?;
vec_try_extend(v, new_cap)?;
debug_assert!(v.capacity() == new_cap);
}
Ok(())
}
#[cfg(not(any(feature = "unstable", feature = "rust_1_57")))]
fn vec_try_extend<T>(v: &mut Vec<T>, new_cap: usize) -> Result<(), TryReserveError> {
let old_len = v.len();
let old_cap: usize = v.capacity();
if old_cap >= new_cap {
return Ok(());
}
let elem_size = core::mem::size_of::<T>();
let new_alloc_size = new_cap
.checked_mul(elem_size)
.filter(|size| *size <= isize::MAX as usize)
.ok_or(TryReserveError::CapacityOverflow)?;
// required for alloc safety
// See https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#safety-1
// Should be unreachable given prior `old_cap >= new_cap` check.
assert!(new_alloc_size > 0);
let align = core::mem::align_of::<T>();
let (new_ptr, layout) = {
if old_cap == 0 {
let layout = Layout::from_size_align(new_alloc_size, align).expect("Invalid layout");
let new_ptr = unsafe { alloc(layout) };
(new_ptr, layout)
} else {
let old_alloc_size = old_cap
.checked_mul(elem_size)
.ok_or(TryReserveError::CapacityOverflow)?;
let layout = Layout::from_size_align(old_alloc_size, align).expect("Invalid layout");
let new_ptr = unsafe { realloc(v.as_mut_ptr() as *mut u8, layout, new_alloc_size) };
(new_ptr, layout)
}
};
if new_ptr.is_null() {
return Err(TryReserveError::AllocError { layout });
}
let new_vec = unsafe { Vec::from_raw_parts(new_ptr.cast(), old_len, new_cap) };
core::mem::forget(core::mem::replace(v, new_vec));
Ok(())
} }
impl<T> FallibleVec<T> for Vec<T> { impl<T> FallibleVec<T> for Vec<T> {
#[inline(always)] #[inline(always)]
fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
#[cfg(all(feature = "unstable", not(feature = "rust_1_57")))] self.try_reserve(additional)
{
self.try_reserve(additional)
}
#[cfg(all(not(feature = "unstable"), not(feature = "rust_1_57")))]
{
vec_try_reserve(self, additional)
}
#[cfg(feature = "rust_1_57")]
{
// TryReserveError is an opaque type in 1.57
self.try_reserve(additional).map_err(|_| {
crate::make_try_reserve_error(self.len(), additional, core::mem::size_of::<T>(), core::mem::align_of::<T>())
})
}
} }
#[inline] #[inline]
fn try_push(&mut self, elem: T) -> Result<(), TryReserveError> { fn try_push(&mut self, elem: T) -> Result<(), TryReserveError> {
if self.len() == self.capacity() { if self.len() == self.capacity() {
vec_try_reserve_for_growth(self, 1)?; self.try_reserve(1)?;
} }
Ok(self.push(elem)) Ok(self.push(elem))
} }
@@ -540,7 +454,7 @@ impl<T> FallibleVec<T> for Vec<T> {
#[inline] #[inline]
fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)> { fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)> {
if self.len() == self.capacity() { if self.len() == self.capacity() {
if let Err(e) = vec_try_reserve_for_growth(self, 1) { if let Err(e) = self.try_reserve(1) {
return Err((elem, e)); return Err((elem, e));
} }
} }
@@ -560,17 +474,19 @@ impl<T> FallibleVec<T> for Vec<T> {
#[inline] #[inline]
fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)> { fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)> {
if self.len() == self.capacity() { if self.len() == self.capacity() {
if let Err(e) = vec_try_reserve_for_growth(self, 1) { if let Err(e) = self.try_reserve(1) {
return Err((element, e)); return Err((element, e));
} }
} }
Ok(self.insert(index, element)) Ok(self.insert(index, element))
} }
#[inline] #[inline]
fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError> { fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError> {
FallibleVec::try_reserve(self, other.len())?; FallibleVec::try_reserve(self, other.len())?;
Ok(self.append(other)) Ok(self.append(other))
} }
fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError> fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where where
T: Copy + Clone, T: Copy + Clone,
@@ -581,6 +497,7 @@ impl<T> FallibleVec<T> for Vec<T> {
} }
Ok(self.resize(new_len, value)) Ok(self.resize(new_len, value))
} }
fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError> fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
where where
F: FnMut() -> T, F: FnMut() -> T,
@@ -591,6 +508,7 @@ impl<T> FallibleVec<T> for Vec<T> {
} }
Ok(self.resize_with(new_len, f)) Ok(self.resize_with(new_len, f))
} }
fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError> fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where where
T: TryClone, T: TryClone,
@@ -600,25 +518,27 @@ impl<T> FallibleVec<T> for Vec<T> {
if new_len > len { if new_len > len {
self.try_extend_with(new_len - len, TryExtendElement(value)) self.try_extend_with(new_len - len, TryExtendElement(value))
} else { } else {
Ok(self.truncate(new_len)) Ok(Truncate::truncate(self, new_len))
} }
} }
#[inline] #[inline]
fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
where where
T: Clone, T: Clone,
{ {
if needs_to_grow(self, other.len()) { if needs_to_grow(self, other.len()) {
vec_try_reserve_for_growth(self, other.len())?; self.try_reserve(other.len())?;
} }
Ok(self.extend_from_slice(other)) Ok(self.extend_from_slice(other))
} }
fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError> fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError>
where where
T: TryClone, T: TryClone,
{ {
if needs_to_grow(self, other.len()) { if needs_to_grow(self, other.len()) {
vec_try_reserve_for_growth(self, other.len())?; self.try_reserve(other.len())?;
} }
let mut len = self.len(); let mut len = self.len();
let mut iterator = other.iter(); let mut iterator = other.iter();
@@ -667,7 +587,7 @@ impl<T> TryExtend<T> for Vec<T> {
mut value: E, mut value: E,
) -> Result<(), TryReserveError> { ) -> Result<(), TryReserveError> {
if needs_to_grow(self, n) { if needs_to_grow(self, n) {
vec_try_reserve_for_growth(self, n)?; self.try_reserve(n)?;
} }
unsafe { unsafe {
@@ -824,16 +744,26 @@ mod tests {
#[test] #[test]
fn try_clone_oom() { fn try_clone_oom() {
let layout = Layout::new::<u8>(); let layout = Layout::new::<u8>();
let v = let v = unsafe {
unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::isize::MAX as usize, core::isize::MAX as usize) }; Vec::<u8>::from_raw_parts(
alloc(layout),
core::isize::MAX as usize,
core::isize::MAX as usize,
)
};
assert!(v.try_clone().is_err()); assert!(v.try_clone().is_err());
} }
#[test] #[test]
fn tryvec_try_clone_oom() { fn tryvec_try_clone_oom() {
let layout = Layout::new::<u8>(); let layout = Layout::new::<u8>();
let inner = let inner = unsafe {
unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::isize::MAX as usize, core::isize::MAX as usize) }; Vec::<u8>::from_raw_parts(
alloc(layout),
core::isize::MAX as usize,
core::isize::MAX as usize,
)
};
let tv = TryVec { inner }; let tv = TryVec { inner };
assert!(tv.try_clone().is_err()); assert!(tv.try_clone().is_err());
} }
@@ -951,15 +881,6 @@ mod tests {
assert_eq!(vec, b"foobar".as_ref()); assert_eq!(vec, b"foobar".as_ref());
} }
#[test]
#[cfg(not(any(feature = "unstable", feature = "rust_1_57")))]
fn try_extend_zst() {
let mut vec: Vec<()> = Vec::new();
assert_eq!(vec.capacity(), core::usize::MAX);
assert!(vec_try_extend(&mut vec, 10).is_ok());
assert!(vec_try_extend(&mut vec, core::usize::MAX).is_ok());
}
#[test] #[test]
fn try_reserve_zst() { fn try_reserve_zst() {
let mut vec: Vec<()> = Vec::new(); let mut vec: Vec<()> = Vec::new();

File diff suppressed because one or more lines are too long

View File

@@ -76,7 +76,7 @@ static_assertions = "1.1.0"
version = "0.3.2" version = "0.3.2"
[dependencies.fallible_collections] [dependencies.fallible_collections]
version = "0.4.9" version = "0.5"
features = ["std_io"] features = ["std_io"]
[dev-dependencies] [dev-dependencies]

View File

@@ -200,7 +200,7 @@ pub enum Status {
ElstBadVersion, ElstBadVersion,
EsdsBadAudioSampleEntry, EsdsBadAudioSampleEntry,
EsdsBadDescriptor, EsdsBadDescriptor,
EsdsDecSpecificIntoTagQuantity, EsdsDecSpecificInfoTagQuantity,
FtypBadSize, FtypBadSize,
FtypNotFirst, FtypNotFirst,
HdlrNameNoNul, HdlrNameNoNul,
@@ -514,7 +514,7 @@ impl From<Status> for &str {
Status::EsdsBadDescriptor => { Status::EsdsBadDescriptor => {
"Invalid descriptor." "Invalid descriptor."
} }
Status::EsdsDecSpecificIntoTagQuantity => { Status::EsdsDecSpecificInfoTagQuantity => {
"There can be only one DecSpecificInfoTag descriptor" "There can be only one DecSpecificInfoTag descriptor"
} }
Status::FtypBadSize => { Status::FtypBadSize => {
@@ -2417,7 +2417,7 @@ pub fn read_avif<T: Read>(f: &mut T, strictness: ParseStrictness) -> Result<Avif
if image_sequence.is_some() { if image_sequence.is_some() {
return Status::MoovBadQuantity.into(); return Status::MoovBadQuantity.into();
} }
image_sequence = Some(read_moov(&mut b, None)?); image_sequence = Some(read_moov(&mut b, None, strictness)?);
} }
BoxType::MediaDataBox => { BoxType::MediaDataBox => {
let file_offset = b.offset(); let file_offset = b.offset();
@@ -4058,7 +4058,7 @@ fn read_iloc<T: Read>(src: &mut BMFFBox<T>) -> Result<TryHashMap<ItemId, ItemLoc
} }
/// Read the contents of a box, including sub boxes. /// Read the contents of a box, including sub boxes.
pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> { pub fn read_mp4<T: Read>(f: &mut T, strictness: ParseStrictness) -> Result<MediaContext> {
let mut context = None; let mut context = None;
let mut found_ftyp = false; let mut found_ftyp = false;
// TODO(kinetik): Top-level parsing should handle zero-sized boxes // TODO(kinetik): Top-level parsing should handle zero-sized boxes
@@ -4087,7 +4087,7 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
debug!("{:?}", ftyp); debug!("{:?}", ftyp);
} }
BoxType::MovieBox => { BoxType::MovieBox => {
context = Some(read_moov(&mut b, context)?); context = Some(read_moov(&mut b, context, strictness)?);
} }
#[cfg(feature = "meta-xml")] #[cfg(feature = "meta-xml")]
BoxType::MetadataBox => { BoxType::MetadataBox => {
@@ -4133,7 +4133,11 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
/// Note that despite the spec indicating "exactly one" moov box should exist at /// Note that despite the spec indicating "exactly one" moov box should exist at
/// the file container level, we support reading and merging multiple moov boxes /// the file container level, we support reading and merging multiple moov boxes
/// such as with tests/test_case_1185230.mp4. /// such as with tests/test_case_1185230.mp4.
fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Result<MediaContext> { fn read_moov<T: Read>(
f: &mut BMFFBox<T>,
context: Option<MediaContext>,
strictness: ParseStrictness,
) -> Result<MediaContext> {
let MediaContext { let MediaContext {
mut timescale, mut timescale,
mut tracks, mut tracks,
@@ -4152,7 +4156,7 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
} }
BoxType::TrackBox => { BoxType::TrackBox => {
let mut track = Track::new(tracks.len()); let mut track = Track::new(tracks.len());
read_trak(&mut b, &mut track)?; read_trak(&mut b, &mut track, strictness)?;
tracks.push(track)?; tracks.push(track)?;
} }
BoxType::MovieExtendsBox => { BoxType::MovieExtendsBox => {
@@ -4262,7 +4266,11 @@ fn read_mehd<T: Read>(src: &mut BMFFBox<T>) -> Result<MediaScaledTime> {
/// Parse a Track Box /// Parse a Track Box
/// See ISOBMFF (ISO 14496-12:2020) § 8.3.1. /// See ISOBMFF (ISO 14496-12:2020) § 8.3.1.
fn read_trak<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> { fn read_trak<T: Read>(
f: &mut BMFFBox<T>,
track: &mut Track,
strictness: ParseStrictness,
) -> Result<()> {
let mut iter = f.box_iter(); let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? { while let Some(mut b) = iter.next_box()? {
match b.head.name { match b.head.name {
@@ -4273,7 +4281,7 @@ fn read_trak<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
debug!("{:?}", tkhd); debug!("{:?}", tkhd);
} }
BoxType::EditBox => read_edts(&mut b, track)?, BoxType::EditBox => read_edts(&mut b, track)?,
BoxType::MediaBox => read_mdia(&mut b, track)?, BoxType::MediaBox => read_mdia(&mut b, track, strictness)?,
BoxType::TrackReferenceBox => track.tref = Some(read_tref(&mut b)?), BoxType::TrackReferenceBox => track.tref = Some(read_tref(&mut b)?),
_ => skip_box_content(&mut b)?, _ => skip_box_content(&mut b)?,
}; };
@@ -4346,7 +4354,11 @@ fn parse_mdhd<T: Read>(
Ok((mdhd, duration, timescale)) Ok((mdhd, duration, timescale))
} }
fn read_mdia<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> { fn read_mdia<T: Read>(
f: &mut BMFFBox<T>,
track: &mut Track,
strictness: ParseStrictness,
) -> Result<()> {
let mut iter = f.box_iter(); let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? { while let Some(mut b) = iter.next_box()? {
match b.head.name { match b.head.name {
@@ -4369,7 +4381,7 @@ fn read_mdia<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
} }
debug!("{:?}", hdlr); debug!("{:?}", hdlr);
} }
BoxType::MediaInformationBox => read_minf(&mut b, track)?, BoxType::MediaInformationBox => read_minf(&mut b, track, strictness)?,
_ => skip_box_content(&mut b)?, _ => skip_box_content(&mut b)?,
}; };
check_parser_state!(b.content); check_parser_state!(b.content);
@@ -4403,11 +4415,15 @@ fn read_tref_auxl<T: Read>(f: &mut BMFFBox<T>) -> Result<TrackReference> {
Ok(TrackReference { track_ids }) Ok(TrackReference { track_ids })
} }
fn read_minf<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> { fn read_minf<T: Read>(
f: &mut BMFFBox<T>,
track: &mut Track,
strictness: ParseStrictness,
) -> Result<()> {
let mut iter = f.box_iter(); let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? { while let Some(mut b) = iter.next_box()? {
match b.head.name { match b.head.name {
BoxType::SampleTableBox => read_stbl(&mut b, track)?, BoxType::SampleTableBox => read_stbl(&mut b, track, strictness)?,
_ => skip_box_content(&mut b)?, _ => skip_box_content(&mut b)?,
}; };
check_parser_state!(b.content); check_parser_state!(b.content);
@@ -4415,12 +4431,16 @@ fn read_minf<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
Ok(()) Ok(())
} }
fn read_stbl<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> { fn read_stbl<T: Read>(
f: &mut BMFFBox<T>,
track: &mut Track,
strictness: ParseStrictness,
) -> Result<()> {
let mut iter = f.box_iter(); let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? { while let Some(mut b) = iter.next_box()? {
match b.head.name { match b.head.name {
BoxType::SampleDescriptionBox => { BoxType::SampleDescriptionBox => {
let stsd = read_stsd(&mut b, track)?; let stsd = read_stsd(&mut b, track, strictness)?;
debug!("{:?}", stsd); debug!("{:?}", stsd);
track.stsd = Some(stsd); track.stsd = Some(stsd);
} }
@@ -4455,7 +4475,7 @@ fn read_stbl<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
track.stss = Some(stss); track.stss = Some(stss);
} }
BoxType::CompositionOffsetBox => { BoxType::CompositionOffsetBox => {
let ctts = read_ctts(&mut b)?; let ctts = read_ctts(&mut b, strictness)?;
debug!("{:?}", ctts); debug!("{:?}", ctts);
track.ctts = Some(ctts); track.ctts = Some(ctts);
} }
@@ -4727,14 +4747,17 @@ fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
/// Parse a Composition Time to Sample Box /// Parse a Composition Time to Sample Box
/// See ISOBMFF (ISO 14496-12:2020) § 8.6.1.3 /// See ISOBMFF (ISO 14496-12:2020) § 8.6.1.3
fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> { fn read_ctts<T: Read>(
src: &mut BMFFBox<T>,
strictness: ParseStrictness,
) -> Result<CompositionOffsetBox> {
let (version, _) = read_fullbox_extra(src)?; let (version, _) = read_fullbox_extra(src)?;
let counts = be_u32(src)?; let counts = be_u32(src)?;
if counts if counts
.checked_mul(8) .checked_mul(8)
.map_or(true, |bytes| u64::from(bytes) > src.bytes_left()) .is_none_or(|bytes| u64::from(bytes) > src.bytes_left())
{ {
return Status::CttsBadSize.into(); return Status::CttsBadSize.into();
} }
@@ -4760,7 +4783,12 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
})?; })?;
} }
check_parser_state!(src.content); if strictness == ParseStrictness::Strict {
check_parser_state!(src.content);
} else {
// Padding may be present in some content.
skip_box_remain(src)?;
}
Ok(CompositionOffsetBox { samples: offsets }) Ok(CompositionOffsetBox { samples: offsets })
} }
@@ -4942,7 +4970,11 @@ fn read_flac_metadata<T: Read>(src: &mut BMFFBox<T>) -> Result<FLACMetadataBlock
} }
/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5 /// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5
fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { fn find_descriptor(
data: &[u8],
esds: &mut ES_Descriptor,
strictness: ParseStrictness,
) -> Result<()> {
// Tags for elementary stream description // Tags for elementary stream description
const ESDESCR_TAG: u8 = 0x03; const ESDESCR_TAG: u8 = 0x03;
const DECODER_CONFIG_TAG: u8 = 0x04; const DECODER_CONFIG_TAG: u8 = 0x04;
@@ -4982,14 +5014,22 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
match tag { match tag {
ESDESCR_TAG => { ESDESCR_TAG => {
read_es_descriptor(descriptor, esds)?; read_es_descriptor(descriptor, esds, strictness)?;
} }
DECODER_CONFIG_TAG => { DECODER_CONFIG_TAG => {
read_dc_descriptor(descriptor, esds)?; read_dc_descriptor(descriptor, esds, strictness)?;
}
DECODER_SPECIFIC_TAG => {
read_ds_descriptor(descriptor, esds)?;
} }
DECODER_SPECIFIC_TAG => match read_ds_descriptor(descriptor, esds, strictness) {
Ok(()) => {}
Err(Error::InvalidData(Status::BitReaderError))
if strictness != ParseStrictness::Strict =>
{
debug!("Unexpected EOS parsing ds descriptor in non-strict mode");
}
Err(e) => {
return Err(e);
}
},
_ => { _ => {
debug!("Unsupported descriptor, tag {}", tag); debug!("Unsupported descriptor, tag {}", tag);
} }
@@ -5014,7 +5054,11 @@ fn get_audio_object_type(bit_reader: &mut BitReader) -> Result<u16> {
} }
/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.7 and probably 14496-3 somewhere? /// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.7 and probably 14496-3 somewhere?
fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { fn read_ds_descriptor(
data: &[u8],
esds: &mut ES_Descriptor,
strictness: ParseStrictness,
) -> Result<()> {
#[cfg(feature = "mp4v")] #[cfg(feature = "mp4v")]
// Check if we are in a Visual esda Box. // Check if we are in a Visual esda Box.
if esds.video_codec != CodecType::Unknown { if esds.video_codec != CodecType::Unknown {
@@ -5170,7 +5214,10 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
esds.audio_sample_rate = Some(sample_frequency_value); esds.audio_sample_rate = Some(sample_frequency_value);
esds.audio_channel_count = Some(channel_counts); esds.audio_channel_count = Some(channel_counts);
if !esds.decoder_specific_data.is_empty() { if !esds.decoder_specific_data.is_empty() {
return Status::EsdsDecSpecificIntoTagQuantity.into(); fail_with_status_if(
strictness == ParseStrictness::Strict,
Status::EsdsDecSpecificInfoTagQuantity,
)?;
} }
esds.decoder_specific_data.extend_from_slice(data)?; esds.decoder_specific_data.extend_from_slice(data)?;
@@ -5191,7 +5238,11 @@ fn read_surround_channel_count(bit_reader: &mut BitReader, channels: u8) -> Resu
} }
/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.6 /// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.6
fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { fn read_dc_descriptor(
data: &[u8],
esds: &mut ES_Descriptor,
strictness: ParseStrictness,
) -> Result<()> {
let des = &mut Cursor::new(data); let des = &mut Cursor::new(data);
let object_profile = des.read_u8()?; let object_profile = des.read_u8()?;
@@ -5207,7 +5258,11 @@ fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
skip(des, 12)?; skip(des, 12)?;
if data.len().to_u64() > des.position() { if data.len().to_u64() > des.position() {
find_descriptor(&data[des.position().try_into()?..data.len()], esds)?; find_descriptor(
&data[des.position().try_into()?..data.len()],
esds,
strictness,
)?;
} }
esds.audio_codec = match object_profile { esds.audio_codec = match object_profile {
@@ -5225,7 +5280,11 @@ fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
} }
/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5 /// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5
fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { fn read_es_descriptor(
data: &[u8],
esds: &mut ES_Descriptor,
strictness: ParseStrictness,
) -> Result<()> {
let des = &mut Cursor::new(data); let des = &mut Cursor::new(data);
skip(des, 2)?; skip(des, 2)?;
@@ -5246,20 +5305,24 @@ fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
} }
if data.len().to_u64() > des.position() { if data.len().to_u64() > des.position() {
find_descriptor(&data[des.position().try_into()?..data.len()], esds)?; find_descriptor(
&data[des.position().try_into()?..data.len()],
esds,
strictness,
)?;
} }
Ok(()) Ok(())
} }
/// See MP4 (ISO 14496-14:2020) § 6.7.2 /// See MP4 (ISO 14496-14:2020) § 6.7.2
fn read_esds<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> { fn read_esds<T: Read>(src: &mut BMFFBox<T>, strictness: ParseStrictness) -> Result<ES_Descriptor> {
let (_, _) = read_fullbox_extra(src)?; let (_, _) = read_fullbox_extra(src)?;
let esds_array = read_buf(src, src.bytes_left())?; let esds_array = read_buf(src, src.bytes_left())?;
let mut es_data = ES_Descriptor::default(); let mut es_data = ES_Descriptor::default();
find_descriptor(&esds_array, &mut es_data)?; find_descriptor(&esds_array, &mut es_data, strictness)?;
es_data.codec_esds = esds_array; es_data.codec_esds = esds_array;
@@ -5558,7 +5621,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
{ {
// Read ES_Descriptor inside an esds box. // Read ES_Descriptor inside an esds box.
// See ISOBMFF (ISO 14496-1:2010) § 7.2.6.5 // See ISOBMFF (ISO 14496-1:2010) § 7.2.6.5
let esds = read_esds(&mut b)?; let esds = read_esds(&mut b, ParseStrictness::Normal)?;
codec_specific = codec_specific =
Some(VideoCodecSpecific::ESDSConfig(esds.decoder_specific_data)); Some(VideoCodecSpecific::ESDSConfig(esds.decoder_specific_data));
} }
@@ -5621,13 +5684,16 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
) )
} }
fn read_qt_wave_atom<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> { fn read_qt_wave_atom<T: Read>(
src: &mut BMFFBox<T>,
strictness: ParseStrictness,
) -> Result<ES_Descriptor> {
let mut codec_specific = None; let mut codec_specific = None;
let mut iter = src.box_iter(); let mut iter = src.box_iter();
while let Some(mut b) = iter.next_box()? { while let Some(mut b) = iter.next_box()? {
match b.head.name { match b.head.name {
BoxType::ESDBox => { BoxType::ESDBox => {
let esds = read_esds(&mut b)?; let esds = read_esds(&mut b, strictness)?;
codec_specific = Some(esds); codec_specific = Some(esds);
} }
_ => skip_box_content(&mut b)?, _ => skip_box_content(&mut b)?,
@@ -5639,7 +5705,10 @@ fn read_qt_wave_atom<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> {
/// Parse an audio description inside an stsd box. /// Parse an audio description inside an stsd box.
/// See ISOBMFF (ISO 14496-12:2020) § 12.2.3 /// See ISOBMFF (ISO 14496-12:2020) § 12.2.3
fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry> { fn read_audio_sample_entry<T: Read>(
src: &mut BMFFBox<T>,
strictness: ParseStrictness,
) -> Result<SampleEntry> {
let name = src.get_header().name; let name = src.get_header().name;
// Skip uninteresting fields. // Skip uninteresting fields.
@@ -5713,7 +5782,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
{ {
return Status::StsdBadAudioSampleEntry.into(); return Status::StsdBadAudioSampleEntry.into();
} }
let esds = read_esds(&mut b)?; let esds = read_esds(&mut b, strictness)?;
codec_type = esds.audio_codec; codec_type = esds.audio_codec;
codec_specific = Some(AudioCodecSpecific::ES_Descriptor(esds)); codec_specific = Some(AudioCodecSpecific::ES_Descriptor(esds));
} }
@@ -5746,7 +5815,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
codec_specific = Some(AudioCodecSpecific::ALACSpecificBox(alac)); codec_specific = Some(AudioCodecSpecific::ALACSpecificBox(alac));
} }
BoxType::QTWaveAtom => { BoxType::QTWaveAtom => {
let qt_esds = read_qt_wave_atom(&mut b)?; let qt_esds = read_qt_wave_atom(&mut b, strictness)?;
codec_type = qt_esds.audio_codec; codec_type = qt_esds.audio_codec;
codec_specific = Some(AudioCodecSpecific::ES_Descriptor(qt_esds)); codec_specific = Some(AudioCodecSpecific::ES_Descriptor(qt_esds));
} }
@@ -5799,7 +5868,11 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleEntry>
/// Parse a stsd box. /// Parse a stsd box.
/// See ISOBMFF (ISO 14496-12:2020) § 8.5.2 /// See ISOBMFF (ISO 14496-12:2020) § 8.5.2
/// See MP4 (ISO 14496-14:2020) § 6.7.2 /// See MP4 (ISO 14496-14:2020) § 6.7.2
fn read_stsd<T: Read>(src: &mut BMFFBox<T>, track: &Track) -> Result<SampleDescriptionBox> { fn read_stsd<T: Read>(
src: &mut BMFFBox<T>,
track: &Track,
strictness: ParseStrictness,
) -> Result<SampleDescriptionBox> {
let (_, flags) = read_fullbox_extra(src)?; let (_, flags) = read_fullbox_extra(src)?;
if flags != 0 { if flags != 0 {
@@ -5819,7 +5892,7 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<T>, track: &Track) -> Result<SampleDescr
TrackType::Video => read_video_sample_entry(&mut b), TrackType::Video => read_video_sample_entry(&mut b),
TrackType::Picture => read_video_sample_entry(&mut b), TrackType::Picture => read_video_sample_entry(&mut b),
TrackType::AuxiliaryVideo => read_video_sample_entry(&mut b), TrackType::AuxiliaryVideo => read_video_sample_entry(&mut b),
TrackType::Audio => read_audio_sample_entry(&mut b), TrackType::Audio => read_audio_sample_entry(&mut b, strictness),
TrackType::Metadata => Err(Error::Unsupported("metadata track")), TrackType::Metadata => Err(Error::Unsupported("metadata track")),
TrackType::Unknown => Err(Error::Unsupported("unknown track type")), TrackType::Unknown => Err(Error::Unsupported("unknown track type")),
}; };

View File

@@ -211,7 +211,7 @@ fn read_truncated_ftyp() {
.B32(0) // minor version .B32(0) // minor version
.append_bytes(b"isom") .append_bytes(b"isom")
}); });
match read_mp4(&mut stream) { match read_mp4(&mut stream, ParseStrictness::Normal) {
Err(Error::UnexpectedEOF) => (), Err(Error::UnexpectedEOF) => (),
Ok(_) => panic!("expected an error result"), Ok(_) => panic!("expected an error result"),
_ => panic!("expected a different error result"), _ => panic!("expected a different error result"),
@@ -649,7 +649,7 @@ fn read_flac() {
}); });
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let r = super::read_audio_sample_entry(&mut stream); let r = super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal);
assert!(r.is_ok()); assert!(r.is_ok());
} }
@@ -740,7 +740,7 @@ fn read_opus() {
}); });
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let r = super::read_audio_sample_entry(&mut stream); let r = super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal);
assert!(r.is_ok()); assert!(r.is_ok());
} }
@@ -830,7 +830,7 @@ fn read_alac() {
}); });
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let r = super::read_audio_sample_entry(&mut stream); let r = super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal);
assert!(r.is_ok()); assert!(r.is_ok());
} }
@@ -852,7 +852,7 @@ fn esds_limit() {
}); });
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
match super::read_audio_sample_entry(&mut stream) { match super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal) {
Err(Error::UnexpectedEOF) => (), Err(Error::UnexpectedEOF) => (),
Ok(_) => panic!("expected an error result"), Ok(_) => panic!("expected an error result"),
_ => panic!("expected a different error result"), _ => panic!("expected a different error result"),
@@ -963,7 +963,8 @@ fn skip_padding_in_stsd() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
super::read_stsd(&mut stream, &super::Track::new(0)).expect("fail to skip padding: stsd"); super::read_stsd(&mut stream, &super::Track::new(0), ParseStrictness::Normal)
.expect("fail to skip padding: stsd");
} }
#[test] #[test]
@@ -1000,8 +1001,8 @@ fn read_qt_wave_atom() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let sample_entry = let sample_entry = super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal)
super::read_audio_sample_entry(&mut stream).expect("fail to read qt wave atom"); .expect("fail to read qt wave atom");
match sample_entry { match sample_entry {
super::SampleEntry::Audio(sample_entry) => { super::SampleEntry::Audio(sample_entry) => {
assert_eq!(sample_entry.codec_type, super::CodecType::MP3) assert_eq!(sample_entry.codec_type, super::CodecType::MP3)
@@ -1025,7 +1026,7 @@ fn read_descriptor_80() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let es = super::read_esds(&mut stream).unwrap(); let es = super::read_esds(&mut stream, ParseStrictness::Normal).unwrap();
assert_eq!(es.audio_codec, super::CodecType::AAC); assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2)); assert_eq!(es.audio_object_type, Some(2));
@@ -1052,7 +1053,7 @@ fn read_esds() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let es = super::read_esds(&mut stream).unwrap(); let es = super::read_esds(&mut stream, ParseStrictness::Normal).unwrap();
assert_eq!(es.audio_codec, super::CodecType::AAC); assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2)); assert_eq!(es.audio_object_type, Some(2));
@@ -1081,7 +1082,7 @@ fn read_esds_aac_type5() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let es = super::read_esds(&mut stream).unwrap(); let es = super::read_esds(&mut stream, ParseStrictness::Normal).unwrap();
assert_eq!(es.audio_codec, super::CodecType::AAC); assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2)); assert_eq!(es.audio_object_type, Some(2));
@@ -1110,7 +1111,7 @@ fn read_esds_mpeg2_aac_lc() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let es = super::read_esds(&mut stream).unwrap(); let es = super::read_esds(&mut stream, ParseStrictness::Normal).unwrap();
assert_eq!(es.audio_codec, super::CodecType::AAC); assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2)); assert_eq!(es.audio_object_type, Some(2));
@@ -1179,7 +1180,7 @@ fn read_esds_one_byte_extension_descriptor() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let es = super::read_esds(&mut stream).unwrap(); let es = super::read_esds(&mut stream, ParseStrictness::Normal).unwrap();
assert_eq!(es.audio_codec, super::CodecType::AAC); assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2)); assert_eq!(es.audio_object_type, Some(2));
@@ -1199,7 +1200,7 @@ fn read_esds_byte_extension_descriptor() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
match super::read_esds(&mut stream) { match super::read_esds(&mut stream, ParseStrictness::Normal) {
Ok(_) => (), Ok(_) => (),
_ => panic!("fail to parse descriptor extension byte length"), _ => panic!("fail to parse descriptor extension byte length"),
} }
@@ -1220,8 +1221,8 @@ fn read_f4v_stsd() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let sample_entry = let sample_entry = super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal)
super::read_audio_sample_entry(&mut stream).expect("failed to read f4v stsd atom"); .expect("failed to read f4v stsd atom");
match sample_entry { match sample_entry {
super::SampleEntry::Audio(sample_entry) => { super::SampleEntry::Audio(sample_entry) => {
assert_eq!(sample_entry.codec_type, super::CodecType::MP3) assert_eq!(sample_entry.codec_type, super::CodecType::MP3)
@@ -1269,7 +1270,7 @@ fn unknown_audio_sample_entry() {
}); });
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
match super::read_audio_sample_entry(&mut stream) { match super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal) {
Ok(super::SampleEntry::Unknown) => (), Ok(super::SampleEntry::Unknown) => (),
_ => panic!("expected a different error result"), _ => panic!("expected a different error result"),
} }
@@ -1291,7 +1292,7 @@ fn read_esds_invalid_descriptor() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
match super::read_esds(&mut stream) { match super::read_esds(&mut stream, ParseStrictness::Normal) {
Err(Error::InvalidData(s)) => assert_eq!(s, Status::EsdsBadDescriptor), Err(Error::InvalidData(s)) => assert_eq!(s, Status::EsdsBadDescriptor),
_ => panic!("unexpected result with invalid descriptor"), _ => panic!("unexpected result with invalid descriptor"),
} }
@@ -1311,12 +1312,36 @@ fn read_esds_redundant_descriptor() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
match super::read_esds(&mut stream) { match super::read_esds(&mut stream, ParseStrictness::Normal) {
Ok(esds) => assert_eq!(esds.audio_codec, super::CodecType::AAC), Ok(esds) => assert_eq!(esds.audio_codec, super::CodecType::AAC),
_ => panic!("unexpected result with invalid descriptor"), _ => panic!("unexpected result with invalid descriptor"),
} }
} }
#[test]
fn read_esds_multiple_descriptors() {
// Permit multiple descriptors in non-strict mode.
// Extracted from BMO #1936124 using Bento4.
// "mp4extract --payload-only moov/trak[0]/mdia/minf/stbl/stsd/mp4a/esds bug1936124.mp4 /dev/stdout | xxd -i -c 15"
let esds = vec![
0x03, 0x1d, 0x00, 0x00, 0x00, 0x04, 0x15, 0x40, 0x15, 0x00, 0x06, 0x00, 0x00, 0x01, 0x77,
0x00, 0x00, 0x01, 0x77, 0x00, 0x05, 0x02, 0x11, 0x90, 0x05, 0x02, 0x11, 0x90, 0x06, 0x01,
0x02,
];
let mut stream = make_box(BoxSize::Auto, b"esds", |s| {
s.B32(0) // reserved
.append_bytes(esds.as_slice())
});
let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap();
match super::read_esds(&mut stream, ParseStrictness::Normal) {
Ok(esds) => assert_eq!(esds.audio_codec, super::CodecType::AAC),
_ => panic!("unexpected result with multiple descriptors"),
}
}
#[test] #[test]
fn read_stsd_lpcm() { fn read_stsd_lpcm() {
// Extract from sample converted by ffmpeg. // Extract from sample converted by ffmpeg.
@@ -1334,7 +1359,8 @@ fn read_stsd_lpcm() {
let mut iter = super::BoxIter::new(&mut stream); let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap(); let mut stream = iter.next_box().unwrap().unwrap();
let sample_entry = super::read_audio_sample_entry(&mut stream).unwrap(); let sample_entry =
super::read_audio_sample_entry(&mut stream, ParseStrictness::Normal).unwrap();
match sample_entry { match sample_entry {
#[allow(clippy::float_cmp)] // The float comparison below is valid and intended. #[allow(clippy::float_cmp)] // The float comparison below is valid and intended.

View File

@@ -243,7 +243,7 @@ fn public_api() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
assert_eq!(context.timescale, Some(mp4::MediaTimeScale(1000))); assert_eq!(context.timescale, Some(mp4::MediaTimeScale(1000)));
for track in context.tracks { for track in context.tracks {
match track.track_type { match track.track_type {
@@ -373,7 +373,7 @@ fn public_metadata() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
let udta = context let udta = context
.userdata .userdata
.expect("didn't find udta") .expect("didn't find udta")
@@ -439,7 +439,7 @@ fn public_metadata_gnre() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
let udta = context let udta = context
.userdata .userdata
.expect("didn't find udta") .expect("didn't find udta")
@@ -504,7 +504,7 @@ fn public_invalid_metadata() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
// Should have userdata. // Should have userdata.
assert!(context.userdata.is_some()); assert!(context.userdata.is_some());
// But it should contain an error. // But it should contain an error.
@@ -547,7 +547,7 @@ fn public_audio_tenc() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let a = match stsd.descriptions.first().expect("expected a SampleEntry") { let a = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -605,7 +605,7 @@ fn public_video_cenc() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let v = match stsd.descriptions.first().expect("expected a SampleEntry") { let v = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -677,7 +677,7 @@ fn public_audio_cbcs() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
assert_eq!(stsd.descriptions.len(), 2); assert_eq!(stsd.descriptions.len(), 2);
@@ -758,7 +758,7 @@ fn public_video_cbcs() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
assert_eq!(stsd.descriptions.len(), 2); assert_eq!(stsd.descriptions.len(), 2);
@@ -816,7 +816,7 @@ fn public_video_av1() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
// track part // track part
assert_eq!(track.duration, Some(mp4::TrackScaledTime(512, 0))); assert_eq!(track.duration, Some(mp4::TrackScaledTime(512, 0)));
@@ -863,7 +863,7 @@ fn public_video_av1() {
#[test] #[test]
fn public_mp4_bug_1185230() { fn public_mp4_bug_1185230() {
let input = &mut File::open("tests/test_case_1185230.mp4").expect("Unknown file"); let input = &mut File::open("tests/test_case_1185230.mp4").expect("Unknown file");
let context = mp4::read_mp4(input).expect("read_mp4 failed"); let context = mp4::read_mp4(input, ParseStrictness::Normal).expect("read_mp4 failed");
let number_video_tracks = context let number_video_tracks = context
.tracks .tracks
.iter() .iter()
@@ -882,7 +882,10 @@ fn public_mp4_bug_1185230() {
fn public_mp4_ctts_overflow() { fn public_mp4_ctts_overflow() {
let input = &mut File::open("tests/clusterfuzz-testcase-minimized-mp4-6093954524250112") let input = &mut File::open("tests/clusterfuzz-testcase-minimized-mp4-6093954524250112")
.expect("Unknown file"); .expect("Unknown file");
assert_eq!(Status::from(mp4::read_mp4(input)), Status::CttsBadSize); assert_eq!(
Status::from(mp4::read_mp4(input, ParseStrictness::Normal)),
Status::CttsBadSize
);
} }
#[test] #[test]
@@ -1427,7 +1430,7 @@ fn public_video_h263() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let v = match stsd.descriptions.first().expect("expected a SampleEntry") { let v = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -1453,7 +1456,7 @@ fn public_video_hevc() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let v = match stsd.descriptions.first().expect("expected a SampleEntry") { let v = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -1479,7 +1482,7 @@ fn public_parse_pasp_h264() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let v = match stsd.descriptions.first().expect("expected a SampleEntry") { let v = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -1509,7 +1512,7 @@ fn public_audio_amrnb() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let a = match stsd.descriptions.first().expect("expected a SampleEntry") { let a = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -1534,7 +1537,7 @@ fn public_audio_amrwb() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let a = match stsd.descriptions.first().expect("expected a SampleEntry") { let a = match stsd.descriptions.first().expect("expected a SampleEntry") {
@@ -1559,7 +1562,7 @@ fn public_video_mp4v() {
fd.read_to_end(&mut buf).expect("File error"); fd.read_to_end(&mut buf).expect("File error");
let mut c = Cursor::new(&buf); let mut c = Cursor::new(&buf);
let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); let context = mp4::read_mp4(&mut c, ParseStrictness::Normal).expect("read_mp4 failed");
for track in context.tracks { for track in context.tracks {
let stsd = track.stsd.expect("expected an stsd"); let stsd = track.stsd.expect("expected an stsd");
let v = match stsd.descriptions.first().expect("expected a SampleEntry") { let v = match stsd.descriptions.first().expect("expected a SampleEntry") {

View File

@@ -1 +1 @@
{"files":{"Cargo.toml":"40db3f983f6b385791f7bb869290919b924f97af77860f81c09ed67c826b4b17","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"f776ed4bbb7b58a5684402a9c5c28dfe1fa02b6b184139b2c2c49384cc1e3723","cbindgen.toml":"62066cd34285ab9e7f1cc5db8950a51e9e080f5a85bd55ad43d7022e4eae2758","examples/dump.rs":"aef3a73e9f5e8dc125e449f7dc7eb8a8c6cfa0edf5f99114d4b90c52e0903613","src/lib.rs":"4f8048452328adeb23e6bfb656e2305b64ed3b3cef30c68509acf1635953212b","tests/test_avis.rs":"f01df914abcb18b562e74c39e15a0fa53159dbe93e9bd8698fab30d792e74645","tests/test_chunk_out_of_range.rs":"4039d0db0ee5973787e4ca14cea510fd958ae5d21856a79240a5e7b826caa18d","tests/test_encryption.rs":"f62131a36b0516caf9e2c48f8aea060d300b0f5c8a32bc54d31cbc97aa25b4e6","tests/test_fragment.rs":"d3f805cc2107481ee9a989818af3addbb3ea1faf7422ea7f4416591d03031318","tests/test_rotation.rs":"23fa4898eca2e17255bc1ba2f538707a6554fb4644bb75f80548ae56a7cd2d44","tests/test_sample_table.rs":"6a0095c155a3618b2338d7252101ff16adaa020f511abdac410548b417aee11b","tests/test_workaround_stsc.rs":"1d17a394f55e1524c30888bfe1e57e2b0457444b79c23eb91b02d2edf859c9ad"},"package":null} {"files":{"Cargo.toml":"e8990ea5795527d3c8cbb46bdc63d36d48451601de3bd87a42dd49b28d7b96d8","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"f776ed4bbb7b58a5684402a9c5c28dfe1fa02b6b184139b2c2c49384cc1e3723","cbindgen.toml":"62066cd34285ab9e7f1cc5db8950a51e9e080f5a85bd55ad43d7022e4eae2758","examples/dump.rs":"aef3a73e9f5e8dc125e449f7dc7eb8a8c6cfa0edf5f99114d4b90c52e0903613","src/lib.rs":"be450bdfe41d259a3f8b48663173ab1d852c66836bdd63af9f3932c925a41a53","tests/test_avis.rs":"f01df914abcb18b562e74c39e15a0fa53159dbe93e9bd8698fab30d792e74645","tests/test_chunk_out_of_range.rs":"4039d0db0ee5973787e4ca14cea510fd958ae5d21856a79240a5e7b826caa18d","tests/test_encryption.rs":"f62131a36b0516caf9e2c48f8aea060d300b0f5c8a32bc54d31cbc97aa25b4e6","tests/test_fragment.rs":"d3f805cc2107481ee9a989818af3addbb3ea1faf7422ea7f4416591d03031318","tests/test_rotation.rs":"23fa4898eca2e17255bc1ba2f538707a6554fb4644bb75f80548ae56a7cd2d44","tests/test_sample_table.rs":"6a0095c155a3618b2338d7252101ff16adaa020f511abdac410548b417aee11b","tests/test_workaround_stsc.rs":"1d17a394f55e1524c30888bfe1e57e2b0457444b79c23eb91b02d2edf859c9ad"},"package":null}

View File

@@ -87,7 +87,7 @@ log = "0.4"
num-traits = "0.2.14" num-traits = "0.2.14"
[dependencies.fallible_collections] [dependencies.fallible_collections]
version = "0.4.9" version = "0.5"
features = ["std_io"] features = ["std_io"]
[dependencies.mp4parse] [dependencies.mp4parse]

View File

@@ -391,8 +391,8 @@ impl ContextParser for Mp4parseParser {
} }
} }
fn read<T: Read>(io: &mut T, _strictness: ParseStrictness) -> mp4parse::Result<Self::Context> { fn read<T: Read>(io: &mut T, strictness: ParseStrictness) -> mp4parse::Result<Self::Context> {
let r = mp4parse::read_mp4(io); let r = mp4parse::read_mp4(io, strictness);
log::debug!("mp4parse::read_mp4 -> {:?}", r); log::debug!("mp4parse::read_mp4 -> {:?}", r);
r r
} }
@@ -442,8 +442,7 @@ pub struct Mp4parseIo {
impl Read for Mp4parseIo { impl Read for Mp4parseIo {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if buf.len() > isize::MAX as usize { if buf.len() > isize::MAX as usize {
return Err(std::io::Error::new( return Err(std::io::Error::other(
std::io::ErrorKind::Other,
"buf length overflow in Mp4parseIo Read impl", "buf length overflow in Mp4parseIo Read impl",
)); ));
} }
@@ -451,10 +450,7 @@ impl Read for Mp4parseIo {
if rv >= 0 { if rv >= 0 {
Ok(rv as usize) Ok(rv as usize)
} else { } else {
Err(std::io::Error::new( Err(std::io::Error::other("I/O error in Mp4parseIo Read impl"))
std::io::ErrorKind::Other,
"I/O error in Mp4parseIo Read impl",
))
} }
} }
} }

View File

@@ -13,7 +13,7 @@ mozglue-static = { path = "../../../../mozglue/static/rust" }
geckoservo = { path = "../../../../servo/ports/geckolib" } geckoservo = { path = "../../../../servo/ports/geckolib" }
kvstore = { path = "../../../components/kvstore" } kvstore = { path = "../../../components/kvstore" }
lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] } lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] }
mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "e64650a686e5c5732395cd059e17cfd3b1e5b63b", features = ["missing-pixi-permitted"] } mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "d3e4d255bd149d341c7e90f5e9fc84e743a8e179", features = ["missing-pixi-permitted"] }
nserror = { path = "../../../../xpcom/rust/nserror" } nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" } nsstring = { path = "../../../../xpcom/rust/nsstring" }
netwerk_helper = { path = "../../../../netwerk/base/rust-helper" } netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
@@ -107,9 +107,6 @@ etagere = { version = "0.2.13", features = ["ffi"] }
url = "2.5.0" url = "2.5.0"
# Since we're building with at least rustc 1.63, enable rust 1.57 features (use of try_reserve methods).
fallible_collections = { version = "0.4", features = ["rust_1_57"] }
libz-rs-sys = { version = "0.4.1", features = ["custom-prefix"], optional = true } libz-rs-sys = { version = "0.4.1", features = ["custom-prefix"], optional = true }
[target.'cfg(any(target_os = "android", target_os = "macos", target_os = "ios", all(target_os = "windows", not(target_arch = "aarch64"))))'.dependencies] [target.'cfg(any(target_os = "android", target_os = "macos", target_os = "ios", all(target_os = "windows", not(target_arch = "aarch64"))))'.dependencies]