зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset a3b2778fa597 (bug 1389470) for leaks. a=oops
MozReview-Commit-ID: 3kkJTmUXdrX --HG-- extra : source : d9a39e5210d07b16cedf7f6b3afc9a850927b631
This commit is contained in:
Родитель
ad92e51651
Коммит
ce7231a8d6
|
@ -763,8 +763,6 @@ MP4MetadataRust::Init()
|
|||
mp4parse_log(true);
|
||||
}
|
||||
|
||||
mp4parse_fallible_allocation(true);
|
||||
|
||||
mp4parse_status rv = mp4parse_read(mRustParser.get());
|
||||
MOZ_LOG(sLog, LogLevel::Debug, ("rust parser returned %d\n", rv));
|
||||
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
|
||||
|
|
|
@ -24,7 +24,6 @@ typedef enum mp4parse_status {
|
|||
mp4parse_status_EOF = 4,
|
||||
mp4parse_status_IO = 5,
|
||||
mp4parse_status_TABLE_TOO_LARGE = 6,
|
||||
mp4parse_status_OOM = 7,
|
||||
} mp4parse_status;
|
||||
|
||||
typedef enum mp4parse_track_type {
|
||||
|
@ -119,8 +118,6 @@ void mp4parse_free(mp4parse_parser* parser);
|
|||
/// Enable `mp4_parser` log.
|
||||
void mp4parse_log(bool enable);
|
||||
|
||||
void mp4parse_fallible_allocation(bool enable);
|
||||
|
||||
/// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
|
||||
mp4parse_status mp4parse_read(mp4parse_parser* parser);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ diff --git a/media/libstagefright/binding/mp4parse/Cargo.toml b/media/libstagefr
|
|||
index ff9422c..814c4c6 100644
|
||||
--- a/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
+++ b/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
@@ -20,20 +20,12 @@ exclude = [
|
||||
@@ -20,19 +20,11 @@ exclude = [
|
||||
]
|
||||
|
||||
-[badges]
|
||||
|
@ -15,11 +15,9 @@ index ff9422c..814c4c6 100644
|
|||
-abort_on_panic = { version = "1.0.0", optional = true }
|
||||
-bitreader = { version = "0.3.0" }
|
||||
-num-traits = "0.1.37"
|
||||
-mp4parse_fallible = { path = "../mp4parse_fallible" }
|
||||
+byteorder = "1.0.0"
|
||||
+bitreader = { version = "0.3.0" }
|
||||
+num-traits = "0.1.37"
|
||||
+mp4parse_fallible = { path = "../mp4parse_fallible" }
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
|
|
@ -24,7 +24,6 @@ exclude = [
|
|||
byteorder = "1.0.0"
|
||||
bitreader = { version = "0.3.0" }
|
||||
num-traits = "0.1.37"
|
||||
mp4parse_fallible = { path = "../mp4parse_fallible" }
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
|
|
@ -11,14 +11,12 @@ extern crate afl;
|
|||
extern crate byteorder;
|
||||
extern crate bitreader;
|
||||
extern crate num_traits;
|
||||
extern crate mp4parse_fallible;
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use bitreader::{BitReader, ReadInto};
|
||||
use std::io::{Read, Take};
|
||||
use std::io::Cursor;
|
||||
use std::cmp;
|
||||
use num_traits::Num;
|
||||
use mp4parse_fallible::FallibleVec;
|
||||
|
||||
mod boxes;
|
||||
use boxes::{BoxType, FourCC};
|
||||
|
@ -32,20 +30,15 @@ const BUF_SIZE_LIMIT: usize = 1024 * 1024;
|
|||
|
||||
// Max table length. Calculating in worth case for one week long video, one
|
||||
// frame per table entry in 30 fps.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24 * 7;
|
||||
|
||||
// Reduce max table length if it is in 32 arch for memory problem.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24;
|
||||
|
||||
static DEBUG_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
|
||||
|
||||
static FALLIBLE_ALLOCATION: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
|
||||
|
||||
pub fn set_fallible_allocation_mode(fallible: bool) {
|
||||
FALLIBLE_ALLOCATION.store(fallible, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn get_fallible_allocation_mode() -> bool {
|
||||
FALLIBLE_ALLOCATION.load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn set_debug_mode(mode: bool) {
|
||||
DEBUG_MODE.store(mode, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
@ -63,37 +56,6 @@ macro_rules! log {
|
|||
)
|
||||
}
|
||||
|
||||
// TODO: vec_push() and vec_reserve() needs to be replaced when Rust supports
|
||||
// fallible memory allocation in raw_vec.
|
||||
pub fn vec_push<T>(vec: &mut Vec<T>, val: T) -> std::result::Result<(), ()> {
|
||||
if get_fallible_allocation_mode() {
|
||||
return vec.try_push(val);
|
||||
}
|
||||
|
||||
vec.push(val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vec_reserve<T>(vec: &mut Vec<T>, size: usize) -> std::result::Result<(), ()> {
|
||||
if get_fallible_allocation_mode() {
|
||||
return vec.try_reserve(size);
|
||||
}
|
||||
|
||||
vec.reserve(size);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reserve_read_buf(size: usize) -> std::result::Result<Vec<u8>, ()> {
|
||||
if get_fallible_allocation_mode() {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
buf.try_reserve(size)?;
|
||||
unsafe { buf.set_len(size); }
|
||||
return Ok(buf);
|
||||
}
|
||||
|
||||
Ok(vec![0; size])
|
||||
}
|
||||
|
||||
/// Describes parser failures.
|
||||
///
|
||||
/// This enum wraps the standard `io::Error` type, unified with
|
||||
|
@ -112,8 +74,6 @@ pub enum Error {
|
|||
NoMoov,
|
||||
/// Parse error caused by table size is over limitation.
|
||||
TableTooLarge,
|
||||
/// Out of memory
|
||||
OutOfMemory,
|
||||
}
|
||||
|
||||
impl From<bitreader::BitReaderError> for Error {
|
||||
|
@ -137,12 +97,6 @@ impl From<std::string::FromUtf8Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<()> for Error {
|
||||
fn from(_: ()) -> Error {
|
||||
Error::OutOfMemory
|
||||
}
|
||||
}
|
||||
|
||||
/// Result shorthand using our Error enum.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
|
@ -735,7 +689,7 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<
|
|||
BoxType::TrackBox => {
|
||||
let mut track = Track::new(context.tracks.len());
|
||||
read_trak(&mut b, &mut track)?;
|
||||
vec_push(&mut context.tracks, track)?;
|
||||
context.tracks.push(track);
|
||||
}
|
||||
BoxType::MovieExtendsBox => {
|
||||
let mvex = read_mvex(&mut b)?;
|
||||
|
@ -745,7 +699,7 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<
|
|||
BoxType::ProtectionSystemSpecificHeaderBox => {
|
||||
let pssh = read_pssh(&mut b)?;
|
||||
log!("{:?}", pssh);
|
||||
vec_push(&mut context.psshs, pssh)?;
|
||||
context.psshs.push(pssh);
|
||||
}
|
||||
_ => skip_box_content(&mut b)?,
|
||||
};
|
||||
|
@ -769,7 +723,7 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHe
|
|||
let count = be_u32_with_limit(pssh)?;
|
||||
for _ in 0..count {
|
||||
let item = read_buf(pssh, 16)?;
|
||||
vec_push(&mut kid, item)?;
|
||||
kid.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,7 +735,7 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHe
|
|||
|
||||
let mut pssh_box = Vec::new();
|
||||
write_be_u32(&mut pssh_box, src.head.size as u32)?;
|
||||
pssh_box.extend_from_slice(b"pssh");
|
||||
pssh_box.append(&mut b"pssh".to_vec());
|
||||
pssh_box.append(&mut box_content);
|
||||
|
||||
Ok(ProtectionSystemSpecificHeaderBox {
|
||||
|
@ -986,7 +940,7 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<T>) -> Result<FileTypeBox> {
|
|||
let brand_count = bytes_left / 4;
|
||||
let mut brands = Vec::new();
|
||||
for _ in 0..brand_count {
|
||||
vec_push(&mut brands, From::from(be_u32(src)?))?;
|
||||
brands.push(From::from(be_u32(src)?));
|
||||
}
|
||||
Ok(FileTypeBox {
|
||||
major_brand: From::from(major),
|
||||
|
@ -1095,12 +1049,12 @@ fn read_elst<T: Read>(src: &mut BMFFBox<T>) -> Result<EditListBox> {
|
|||
};
|
||||
let media_rate_integer = be_i16(src)?;
|
||||
let media_rate_fraction = be_i16(src)?;
|
||||
vec_push(&mut edits, Edit {
|
||||
edits.push(Edit {
|
||||
segment_duration: segment_duration,
|
||||
media_time: media_time,
|
||||
media_rate_integer: media_rate_integer,
|
||||
media_rate_fraction: media_rate_fraction,
|
||||
})?;
|
||||
})
|
||||
}
|
||||
|
||||
Ok(EditListBox {
|
||||
|
@ -1156,7 +1110,7 @@ fn read_stco<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
|
|||
let offset_count = be_u32_with_limit(src)?;
|
||||
let mut offsets = Vec::new();
|
||||
for _ in 0..offset_count {
|
||||
vec_push(&mut offsets, be_u32(src)? as u64)?;
|
||||
offsets.push(be_u32(src)? as u64);
|
||||
}
|
||||
|
||||
// Padding could be added in some contents.
|
||||
|
@ -1173,7 +1127,7 @@ fn read_co64<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
|
|||
let offset_count = be_u32_with_limit(src)?;
|
||||
let mut offsets = Vec::new();
|
||||
for _ in 0..offset_count {
|
||||
vec_push(&mut offsets, be_u64(src)?)?;
|
||||
offsets.push(be_u64(src)?);
|
||||
}
|
||||
|
||||
// Padding could be added in some contents.
|
||||
|
@ -1190,7 +1144,7 @@ fn read_stss<T: Read>(src: &mut BMFFBox<T>) -> Result<SyncSampleBox> {
|
|||
let sample_count = be_u32_with_limit(src)?;
|
||||
let mut samples = Vec::new();
|
||||
for _ in 0..sample_count {
|
||||
vec_push(&mut samples, be_u32(src)?)?;
|
||||
samples.push(be_u32(src)?);
|
||||
}
|
||||
|
||||
// Padding could be added in some contents.
|
||||
|
@ -1210,11 +1164,11 @@ fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
|
|||
let first_chunk = be_u32(src)?;
|
||||
let samples_per_chunk = be_u32_with_limit(src)?;
|
||||
let sample_description_index = be_u32(src)?;
|
||||
vec_push(&mut samples, SampleToChunk {
|
||||
samples.push(SampleToChunk {
|
||||
first_chunk: first_chunk,
|
||||
samples_per_chunk: samples_per_chunk,
|
||||
sample_description_index: sample_description_index,
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
// Padding could be added in some contents.
|
||||
|
@ -1249,10 +1203,10 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
|
|||
return Err(Error::InvalidData("unsupported version in 'ctts' box"));
|
||||
}
|
||||
};
|
||||
vec_push(&mut offsets, TimeOffset {
|
||||
offsets.push(TimeOffset {
|
||||
sample_count: sample_count,
|
||||
time_offset: time_offset,
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
skip_box_remain(src)?;
|
||||
|
@ -1270,7 +1224,7 @@ fn read_stsz<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleSizeBox> {
|
|||
let mut sample_sizes = Vec::new();
|
||||
if sample_size == 0 {
|
||||
for _ in 0..sample_count {
|
||||
vec_push(&mut sample_sizes, be_u32(src)?)?;
|
||||
sample_sizes.push(be_u32(src)?);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1291,10 +1245,10 @@ fn read_stts<T: Read>(src: &mut BMFFBox<T>) -> Result<TimeToSampleBox> {
|
|||
for _ in 0..sample_count {
|
||||
let sample_count = be_u32_with_limit(src)?;
|
||||
let sample_delta = be_u32(src)?;
|
||||
vec_push(&mut samples, Sample {
|
||||
samples.push(Sample {
|
||||
sample_count: sample_count,
|
||||
sample_delta: sample_delta,
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
// Padding could be added in some contents.
|
||||
|
@ -1501,7 +1455,7 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
|
|||
esds.audio_sample_rate = sample_frequency;
|
||||
esds.audio_channel_count = Some(channel_counts);
|
||||
assert!(esds.decoder_specific_data.is_empty());
|
||||
esds.decoder_specific_data.extend_from_slice(data);
|
||||
esds.decoder_specific_data.extend(data.iter());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1589,7 +1543,7 @@ fn read_dfla<T: Read>(src: &mut BMFFBox<T>) -> Result<FLACSpecificBox> {
|
|||
let mut blocks = Vec::new();
|
||||
while src.bytes_left() > 0 {
|
||||
let block = read_flac_metadata(src)?;
|
||||
vec_push(&mut blocks, block)?;
|
||||
blocks.push(block);
|
||||
}
|
||||
// The box must have at least one meta block, and the first block
|
||||
// must be the METADATA_BLOCK_STREAMINFO
|
||||
|
@ -1783,7 +1737,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
}
|
||||
let sinf = read_sinf(&mut b)?;
|
||||
log!("{:?} (sinf)", sinf);
|
||||
vec_push(&mut protection_info, sinf)?;
|
||||
protection_info.push(sinf);
|
||||
}
|
||||
_ => {
|
||||
log!("Unsupported video codec, box {:?} found", b.head.name);
|
||||
|
@ -1908,7 +1862,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
let sinf = read_sinf(&mut b)?;
|
||||
log!("{:?} (sinf)", sinf);
|
||||
codec_type = CodecType::EncryptedAudio;
|
||||
vec_push(&mut protection_info, sinf)?;
|
||||
protection_info.push(sinf);
|
||||
}
|
||||
_ => {
|
||||
log!("Unsupported audio codec, box {:?} found", b.head.name);
|
||||
|
@ -1966,7 +1920,7 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> Result<SampleD
|
|||
} else {
|
||||
log!("** don't know how to handle multiple descriptions **");
|
||||
}
|
||||
vec_push(&mut descriptions, description)?;
|
||||
descriptions.push(description);
|
||||
check_parser_state!(b.content);
|
||||
if descriptions.len() == description_count as usize {
|
||||
break;
|
||||
|
@ -2061,15 +2015,12 @@ fn read_buf<T: ReadBytesExt>(src: &mut T, size: usize) -> Result<Vec<u8>> {
|
|||
if size > BUF_SIZE_LIMIT {
|
||||
return Err(Error::InvalidData("read_buf size exceeds BUF_SIZE_LIMIT"));
|
||||
}
|
||||
if let Ok(mut buf) = reserve_read_buf(size) {
|
||||
let r = src.read(&mut buf)?;
|
||||
if r != size {
|
||||
return Err(Error::InvalidData("failed buffer read"));
|
||||
}
|
||||
return Ok(buf);
|
||||
let mut buf = vec![0; size];
|
||||
let r = src.read(&mut buf)?;
|
||||
if r != size {
|
||||
return Err(Error::InvalidData("failed buffer read"));
|
||||
}
|
||||
|
||||
Err(Error::OutOfMemory)
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn be_i16<T: ReadBytesExt>(src: &mut T) -> Result<i16> {
|
||||
|
|
|
@ -58,7 +58,6 @@ use mp4parse::TrackScaledTime;
|
|||
use mp4parse::serialize_opus_header;
|
||||
use mp4parse::CodecType;
|
||||
use mp4parse::Track;
|
||||
use mp4parse::vec_push;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
|
@ -71,7 +70,6 @@ pub enum mp4parse_status {
|
|||
EOF = 4,
|
||||
IO = 5,
|
||||
TABLE_TOO_LARGE = 6,
|
||||
OOM = 7,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
|
@ -310,11 +308,6 @@ pub unsafe extern fn mp4parse_log(enable: bool) {
|
|||
mp4parse::set_debug_mode(enable);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn mp4parse_fallible_allocation(enable: bool) {
|
||||
mp4parse::set_fallible_allocation_mode(enable);
|
||||
}
|
||||
|
||||
/// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn mp4parse_read(parser: *mut mp4parse_parser) -> mp4parse_status {
|
||||
|
@ -323,8 +316,8 @@ pub unsafe extern fn mp4parse_read(parser: *mut mp4parse_parser) -> mp4parse_sta
|
|||
return mp4parse_status::BAD_ARG;
|
||||
}
|
||||
|
||||
let context = (*parser).context_mut();
|
||||
let io = (*parser).io_mut();
|
||||
let mut context = (*parser).context_mut();
|
||||
let mut io = (*parser).io_mut();
|
||||
|
||||
let r = read_mp4(io, context);
|
||||
match r {
|
||||
|
@ -345,7 +338,6 @@ pub unsafe extern fn mp4parse_read(parser: *mut mp4parse_parser) -> mp4parse_sta
|
|||
mp4parse_status::IO
|
||||
},
|
||||
Err(Error::TableTooLarge) => mp4parse_status::TABLE_TOO_LARGE,
|
||||
Err(Error::OutOfMemory) => mp4parse_status::OOM,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -908,17 +900,16 @@ fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4p
|
|||
}
|
||||
cur_position = end_offset;
|
||||
|
||||
let res = vec_push(&mut sample_table, mp4parse_indice {
|
||||
start_offset: start_offset,
|
||||
end_offset: end_offset,
|
||||
start_composition: 0,
|
||||
end_composition: 0,
|
||||
start_decode: 0,
|
||||
sync: !has_sync_table,
|
||||
});
|
||||
if res.is_err() {
|
||||
return None;
|
||||
}
|
||||
sample_table.push(
|
||||
mp4parse_indice {
|
||||
start_offset: start_offset,
|
||||
end_offset: end_offset,
|
||||
start_composition: 0,
|
||||
end_composition: 0,
|
||||
start_decode: 0,
|
||||
sync: !has_sync_table,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,13 +977,12 @@ fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4p
|
|||
//
|
||||
// Composition end time is not in specification. However, gecko needs it, so we need to
|
||||
// calculate to correct the composition end time.
|
||||
if sample_table.len() > 0 {
|
||||
if track.ctts.is_some() {
|
||||
// Create an index table refers to sample_table and sorted by start_composisiton time.
|
||||
let mut sort_table = Vec::new();
|
||||
sort_table.reserve(sample_table.len());
|
||||
for i in 0 .. sample_table.len() {
|
||||
if vec_push(&mut sort_table, i).is_err() {
|
||||
return None;
|
||||
}
|
||||
sort_table.push(i);
|
||||
}
|
||||
|
||||
sort_table.sort_by_key(|i| {
|
||||
|
@ -1126,7 +1116,7 @@ extern fn error_read(_: *mut u8, _: usize, _: *mut std::os::raw::c_void) -> isiz
|
|||
|
||||
#[cfg(test)]
|
||||
extern fn valid_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize {
|
||||
let input: &mut std::fs::File = unsafe { &mut *(userdata as *mut _) };
|
||||
let mut input: &mut std::fs::File = unsafe { &mut *(userdata as *mut _) };
|
||||
|
||||
let mut buf = unsafe { std::slice::from_raw_parts_mut(buf, size) };
|
||||
match input.read(&mut buf) {
|
||||
|
@ -1290,8 +1280,6 @@ fn get_track_count_poisoned_parser() {
|
|||
let mut count: u32 = 0;
|
||||
let rv = mp4parse_get_track_count(parser, &mut count);
|
||||
assert_eq!(rv, mp4parse_status::BAD_ARG);
|
||||
|
||||
mp4parse_free(parser);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
[package]
|
||||
name = "mp4parse_fallible"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MPL-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "mp4parse_fallible"
|
||||
path = "lib.rs"
|
|
@ -1,2 +0,0 @@
|
|||
This is from https://github.com/servo/servo/tree/master/components/fallible
|
||||
with modificaion for mp4 demuxer.
|
|
@ -1,92 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::mem;
|
||||
use std::vec::Vec;
|
||||
|
||||
extern "C" {
|
||||
fn realloc(ptr: *mut u8, bytes: usize) -> *mut u8;
|
||||
fn malloc(bytes: usize) -> *mut u8;
|
||||
}
|
||||
|
||||
pub trait FallibleVec<T> {
|
||||
/// Append |val| to the end of |vec|. Returns Ok(()) on success,
|
||||
/// Err(()) if it fails, which can only be due to lack of memory.
|
||||
fn try_push(&mut self, value: T) -> Result<(), ()>;
|
||||
|
||||
/// Expand the vector size. Return Ok(()) on success, Err(()) if it
|
||||
/// fails.
|
||||
fn try_reserve(&mut self, new_cap: usize) -> Result<(), ()>;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Vec
|
||||
|
||||
impl<T> FallibleVec<T> for Vec<T> {
|
||||
#[inline]
|
||||
fn try_push(&mut self, val: T) -> Result<(), ()> {
|
||||
if self.capacity() == self.len() {
|
||||
let old_cap: usize = self.capacity();
|
||||
let new_cap: usize
|
||||
= if old_cap == 0 { 4 } else { old_cap.checked_mul(2).ok_or(()) ? };
|
||||
|
||||
try_extend_vec(self, new_cap)?;
|
||||
debug_assert!(self.capacity() > self.len());
|
||||
}
|
||||
self.push(val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_reserve(&mut self, cap: usize) -> Result<(), ()> {
|
||||
let new_cap = cap + self.capacity();
|
||||
try_extend_vec(self, new_cap)?;
|
||||
debug_assert!(self.capacity() == new_cap);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn try_extend_vec<T>(vec: &mut Vec<T>, new_cap: usize) -> Result<(), ()> {
|
||||
let old_ptr = vec.as_mut_ptr();
|
||||
let old_len = vec.len();
|
||||
|
||||
let old_cap: usize = vec.capacity();
|
||||
|
||||
if old_cap > new_cap {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let new_size_bytes
|
||||
= new_cap.checked_mul(mem::size_of::<T>()).ok_or(()) ? ;
|
||||
|
||||
let new_ptr = unsafe {
|
||||
if old_cap == 0 {
|
||||
malloc(new_size_bytes)
|
||||
} else {
|
||||
realloc(old_ptr as *mut u8, new_size_bytes)
|
||||
}
|
||||
};
|
||||
|
||||
if new_ptr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let new_vec = unsafe {
|
||||
Vec::from_raw_parts(new_ptr as *mut T, old_len, new_cap)
|
||||
};
|
||||
|
||||
mem::forget(mem::replace(vec, new_vec));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oom_test() {
|
||||
let mut vec: Vec<char> = Vec::new();
|
||||
match vec.try_reserve(std::usize::MAX) {
|
||||
Ok(_) => panic!("it should be OOM"),
|
||||
_ => (),
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
# Script to update mp4parse-rust sources to latest upstream
|
||||
|
||||
# Default version.
|
||||
VER=759cf90957b1fd5a01632b1aa90cead16c26d0db
|
||||
VER=81260ded506dce968716720e10544c510f37d222
|
||||
|
||||
# Accept version or commit from the command line.
|
||||
if test -n "$1"; then
|
||||
|
@ -38,9 +38,6 @@ cp _upstream/mp4parse/mp4parse_capi/Cargo.toml mp4parse_capi/
|
|||
cp _upstream/mp4parse/mp4parse_capi/build.rs mp4parse_capi/
|
||||
cp _upstream/mp4parse/mp4parse_capi/include/mp4parse.h include/
|
||||
cp _upstream/mp4parse/mp4parse_capi/src/*.rs mp4parse_capi/src/
|
||||
rm -rf mp4parse_fallible
|
||||
mkdir -p mp4parse_fallible
|
||||
cp _upstream/mp4parse/mp4parse_fallible/* mp4parse_fallible/
|
||||
|
||||
echo "Applying patches..."
|
||||
patch -p4 < mp4parse-cargo.patch
|
||||
|
|
|
@ -802,7 +802,6 @@ version = "0.8.0"
|
|||
dependencies = [
|
||||
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse_fallible 0.0.1",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -819,10 +818,6 @@ dependencies = [
|
|||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse_fallible"
|
||||
version = "0.0.1"
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.31"
|
||||
|
|
|
@ -800,7 +800,6 @@ version = "0.8.0"
|
|||
dependencies = [
|
||||
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse_fallible 0.0.1",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -813,10 +812,6 @@ dependencies = [
|
|||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse_fallible"
|
||||
version = "0.0.1"
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.31"
|
||||
|
|
Загрузка…
Ссылка в новой задаче