Skip to content

Commit b97b249

Browse files
authored
Merge pull request #203 from mozilla/mp4parse_new-refactor
Refactor mp4parse_new to return Mp4parseStatus
2 parents 0f883c3 + cf3f2c7 commit b97b249

9 files changed

+92
-111
lines changed

mp4parse_capi/examples/dump.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ fn dump_file(filename: &str) {
2828
};
2929

3030
unsafe {
31-
let mut rv = Mp4parseStatus::Invalid;
32-
let parser = mp4parse_new(&io, &mut rv);
31+
let mut parser = std::ptr::null_mut();
32+
let rv = mp4parse_new(&io, &mut parser);
3333

3434
match rv {
3535
Mp4parseStatus::Ok => (),

mp4parse_capi/examples/test.cc

+13-14
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,23 @@ intptr_t io_read(uint8_t *buffer, uintptr_t size, void *userdata)
3535

3636
void test_arg_validation()
3737
{
38-
Mp4parseParser *parser = mp4parse_new(nullptr, nullptr);
39-
assert(parser == nullptr);
38+
Mp4parseParser *parser = nullptr;
39+
Mp4parseStatus rv = mp4parse_new(nullptr, nullptr);
40+
assert(rv == MP4PARSE_STATUS_BAD_ARG);
4041

41-
Mp4parseStatus rv = MP4PARSE_STATUS_INVALID;
42-
parser = mp4parse_new(nullptr, &rv);
42+
rv = mp4parse_new(nullptr, &parser);
4343
assert(rv == MP4PARSE_STATUS_BAD_ARG);
4444
assert(parser == nullptr);
4545

4646
Mp4parseIo io = { nullptr, nullptr };
47-
rv = MP4PARSE_STATUS_INVALID;
48-
parser = mp4parse_new(&io, &rv);
47+
rv = mp4parse_new(&io, &parser);
4948
assert(rv == MP4PARSE_STATUS_BAD_ARG);
5049
assert(parser == nullptr);
5150

5251
int dummy_value = 42;
5352
io = { nullptr, &dummy_value };
54-
rv = MP4PARSE_STATUS_INVALID;
55-
parser = mp4parse_new(&io, &rv);
53+
parser = nullptr;
54+
rv = mp4parse_new(&io, &parser);
5655
assert(rv == MP4PARSE_STATUS_BAD_ARG);
5756
assert(parser == nullptr);
5857

@@ -75,8 +74,8 @@ void test_arg_validation_with_parser()
7574
{
7675
int dummy_value = 42;
7776
Mp4parseIo io = { error_read, &dummy_value };
78-
Mp4parseStatus rv = MP4PARSE_STATUS_INVALID;
79-
Mp4parseParser *parser = mp4parse_new(&io, &rv);
77+
Mp4parseParser *parser = nullptr;
78+
Mp4parseStatus rv = mp4parse_new(&io, &parser);
8079
assert(rv == MP4PARSE_STATUS_IO);
8180
assert(parser == nullptr);
8281

@@ -97,8 +96,8 @@ void test_arg_validation_with_data(const std::string& filename)
9796
FILE* f = fopen(filename.c_str(), "rb");
9897
assert(f != nullptr);
9998
Mp4parseIo io = { io_read, f };
100-
Mp4parseStatus rv = MP4PARSE_STATUS_INVALID;
101-
Mp4parseParser *parser = mp4parse_new(&io, &rv);
99+
Mp4parseParser *parser = nullptr;
100+
Mp4parseStatus rv = mp4parse_new(&io, &parser);
102101
assert(rv == MP4PARSE_STATUS_OK);
103102
assert(parser != nullptr);
104103

@@ -183,8 +182,8 @@ int32_t read_file(const char* filename)
183182

184183
fprintf(stderr, "Parsing file '%s'.\n", filename);
185184
Mp4parseIo io = { io_read, f };
186-
Mp4parseStatus rv = MP4PARSE_STATUS_INVALID;
187-
Mp4parseParser *parser = mp4parse_new(&io, &rv);
185+
Mp4parseParser *parser = nullptr;
186+
Mp4parseStatus rv = mp4parse_new(&io, &parser);
188187

189188
if (rv != MP4PARSE_STATUS_OK) {
190189
assert(parser == nullptr);

mp4parse_capi/src/lib.rs

+55-73
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
//! read: Some(buf_read),
2323
//! userdata: &mut file as *mut _ as *mut std::os::raw::c_void
2424
//! };
25-
//! let mut rv = mp4parse_capi::Mp4parseStatus::Invalid;
25+
//! let mut parser = std::ptr::null_mut();
2626
//! unsafe {
27-
//! let parser = mp4parse_capi::mp4parse_new(&io, &mut rv);
27+
//! let rv = mp4parse_capi::mp4parse_new(&io, &mut parser);
2828
//! assert_eq!(rv, mp4parse_capi::Mp4parseStatus::Ok);
2929
//! assert!(!parser.is_null());
3030
//! mp4parse_capi::mp4parse_free(parser);
@@ -417,76 +417,66 @@ impl Read for Mp4parseIo {
417417
///
418418
/// # Safety
419419
///
420-
/// This function is unsafe because it dereferences the io pointer given to it.
421-
/// The caller should ensure that the `Mp4ParseIo` struct passed in is a valid
422-
/// pointer. The caller should also ensure the members of io are valid: the
423-
/// `read` function should be sanely implemented, and the `userdata` pointer
424-
/// should be valid. The `status_out` is also dereferenced and must point to
425-
/// a valid Mp4parseStatus.
426-
///
427-
/// On a successful the variable pointed to by `status_out` will be set to
428-
/// `Mp4parseStatus::Ok` and the return value will be a non-NULL pointer to
429-
/// an `Mp4parseParser`. If there is any sort of error, the return value will
430-
/// be NULL and the type of error will be set in the variable pointed to by
431-
/// `status_out`, ensuring the consumer never has access to potentially invalid
432-
/// parsed data.
420+
/// This function is unsafe because it dereferences the `io` and `parser_out`
421+
/// pointers given to it. The caller should ensure that the `Mp4ParseIo`
422+
/// struct passed in is a valid pointer. The caller should also ensure the
423+
/// members of io are valid: the `read` function should be sanely implemented,
424+
/// and the `userdata` pointer should be valid. The `parser_out` should be a
425+
/// valid pointer to a location containing a null pointer. Upon successful
426+
/// return (`Mp4parseStatus::Ok`), that location will contain the address of
427+
/// an `Mp4parseParser` allocated by this function.
433428
///
434429
/// To avoid leaking memory, any successful return of this function must be
435430
/// paired with a call to `mp4parse_free`. In the event of error, no memory
436431
/// will be allocated and `mp4parse_free` must *not* be called.
437432
#[no_mangle]
438433
pub unsafe extern "C" fn mp4parse_new(
439434
io: *const Mp4parseIo,
440-
status_out: *mut Mp4parseStatus,
441-
) -> *mut Mp4parseParser {
442-
mp4parse_new_common(io, status_out)
435+
parser_out: *mut *mut Mp4parseParser,
436+
) -> Mp4parseStatus {
437+
mp4parse_new_common(io, parser_out)
443438
}
444439

445440
/// Allocate an `Mp4parseAvifParser*` to read from the supplied `Mp4parseIo`.
446441
///
447-
/// See mp4parse_new; this function is identical except that it returns a
448-
/// pointer to an `Mp4parseAvifParser`, which (when non-null) must be paired
449-
/// with a call to mp4parse_avif_free.
442+
/// See mp4parse_new; this function is identical except that it allocates an
443+
/// `Mp4parseAvifParser`, which (when successful) must be paired with a call
444+
/// to mp4parse_avif_free.
450445
///
451446
/// # Safety
452447
///
453448
/// Same as mp4parse_new.
454449
#[no_mangle]
455450
pub unsafe extern "C" fn mp4parse_avif_new(
456451
io: *const Mp4parseIo,
457-
status_out: *mut Mp4parseStatus,
458-
) -> *mut Mp4parseAvifParser {
459-
mp4parse_new_common(io, status_out)
452+
parser_out: *mut *mut Mp4parseAvifParser,
453+
) -> Mp4parseStatus {
454+
mp4parse_new_common(io, parser_out)
460455
}
461456

462457
unsafe fn mp4parse_new_common<P: ContextParser>(
463458
io: *const Mp4parseIo,
464-
status_out: *mut Mp4parseStatus,
465-
) -> *mut P {
459+
parser_out: *mut *mut P,
460+
) -> Mp4parseStatus {
466461
// Validate arguments from C.
467-
if io.is_null() || (*io).userdata.is_null() || (*io).read.is_none() || status_out.is_null() {
468-
set_if_non_null(status_out, Mp4parseStatus::BadArg);
469-
std::ptr::null_mut()
462+
if io.is_null()
463+
|| (*io).userdata.is_null()
464+
|| (*io).read.is_none()
465+
|| parser_out.is_null()
466+
|| !(*parser_out).is_null()
467+
{
468+
Mp4parseStatus::BadArg
470469
} else {
471470
match mp4parse_new_common_safe(&mut (*io).clone()) {
472471
Ok(parser) => {
473-
set_if_non_null(status_out, Mp4parseStatus::Ok);
474-
parser
475-
}
476-
Err(status) => {
477-
set_if_non_null(status_out, status);
478-
std::ptr::null_mut()
472+
*parser_out = parser;
473+
Mp4parseStatus::Ok
479474
}
475+
Err(status) => status,
480476
}
481477
}
482478
}
483479

484-
unsafe fn set_if_non_null<T>(ptr: *mut T, val: T) {
485-
if !ptr.is_null() {
486-
*ptr = val;
487-
}
488-
}
489-
490480
fn mp4parse_new_common_safe<T: Read, P: ContextParser>(
491481
io: &mut T,
492482
) -> Result<*mut P, Mp4parseStatus> {
@@ -1618,12 +1608,12 @@ fn get_track_count_null_parser() {
16181608
#[test]
16191609
fn arg_validation() {
16201610
unsafe {
1621-
let parser = mp4parse_new(std::ptr::null(), std::ptr::null_mut());
1622-
assert!(parser.is_null());
1611+
let rv = mp4parse_new(std::ptr::null(), std::ptr::null_mut());
1612+
assert_eq!(rv, Mp4parseStatus::BadArg);
16231613

16241614
// Passing a null Mp4parseIo is an error.
1625-
let mut rv = Mp4parseStatus::Invalid;
1626-
let parser = mp4parse_new(std::ptr::null(), &mut rv);
1615+
let mut parser = std::ptr::null_mut();
1616+
let rv = mp4parse_new(std::ptr::null(), &mut parser);
16271617
assert_eq!(rv, Mp4parseStatus::BadArg);
16281618
assert!(parser.is_null());
16291619

@@ -1634,8 +1624,8 @@ fn arg_validation() {
16341624
read: None,
16351625
userdata: null_mut,
16361626
};
1637-
let mut rv = Mp4parseStatus::Invalid;
1638-
let parser = mp4parse_new(&io, &mut rv);
1627+
let mut parser = std::ptr::null_mut();
1628+
let rv = mp4parse_new(&io, &mut parser);
16391629
assert_eq!(rv, Mp4parseStatus::BadArg);
16401630
assert!(parser.is_null());
16411631

@@ -1644,8 +1634,8 @@ fn arg_validation() {
16441634
read: None,
16451635
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
16461636
};
1647-
let mut rv = Mp4parseStatus::Invalid;
1648-
let parser = mp4parse_new(&io, &mut rv);
1637+
let mut parser = std::ptr::null_mut();
1638+
let rv = mp4parse_new(&io, &mut parser);
16491639
assert_eq!(rv, Mp4parseStatus::BadArg);
16501640
assert!(parser.is_null());
16511641

@@ -1680,6 +1670,18 @@ fn arg_validation() {
16801670
}
16811671
}
16821672

1673+
#[test]
1674+
fn parser_input_must_be_null() {
1675+
let mut dummy_value = 42;
1676+
let io = Mp4parseIo {
1677+
read: Some(error_read),
1678+
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
1679+
};
1680+
let mut parser = 0xDEADBEEF as *mut _;
1681+
let rv = unsafe { mp4parse_new(&io, &mut parser) };
1682+
assert_eq!(rv, Mp4parseStatus::BadArg);
1683+
}
1684+
16831685
#[test]
16841686
fn arg_validation_with_parser() {
16851687
unsafe {
@@ -1688,8 +1690,8 @@ fn arg_validation_with_parser() {
16881690
read: Some(error_read),
16891691
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
16901692
};
1691-
let mut rv = Mp4parseStatus::Invalid;
1692-
let parser = mp4parse_new(&io, &mut rv);
1693+
let mut parser = std::ptr::null_mut();
1694+
let rv = mp4parse_new(&io, &mut parser);
16931695
assert_eq!(rv, Mp4parseStatus::Io);
16941696
assert!(parser.is_null());
16951697

@@ -1738,35 +1740,15 @@ fn arg_validation_with_parser() {
17381740
}
17391741
}
17401742

1741-
#[test]
1742-
fn get_track_count_poisoned_parser() {
1743-
unsafe {
1744-
let mut dummy_value = 42;
1745-
let io = Mp4parseIo {
1746-
read: Some(error_read),
1747-
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
1748-
};
1749-
let mut rv = Mp4parseStatus::Invalid;
1750-
let parser = mp4parse_new(&io, &mut rv);
1751-
assert_eq!(rv, Mp4parseStatus::Io);
1752-
assert!(parser.is_null());
1753-
1754-
let mut count: u32 = 0;
1755-
let rv = mp4parse_get_track_count(parser, &mut count);
1756-
assert_eq!(rv, Mp4parseStatus::BadArg);
1757-
}
1758-
}
1759-
17601743
#[cfg(test)]
17611744
fn parse_minimal_mp4() -> *mut Mp4parseParser {
17621745
let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap();
17631746
let io = Mp4parseIo {
17641747
read: Some(valid_read),
17651748
userdata: &mut file as *mut _ as *mut std::os::raw::c_void,
17661749
};
1767-
let mut rv = Mp4parseStatus::Invalid;
1768-
let parser;
1769-
unsafe { parser = mp4parse_new(&io, &mut rv) }
1750+
let mut parser = std::ptr::null_mut();
1751+
let rv = unsafe { mp4parse_new(&io, &mut parser) };
17701752
assert_eq!(Mp4parseStatus::Ok, rv);
17711753
parser
17721754
}

mp4parse_capi/tests/test_chunk_out_of_range.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ fn parse_out_of_chunk_range() {
2020
};
2121

2222
unsafe {
23-
let mut rv = Mp4parseStatus::Invalid;
24-
let parser = mp4parse_new(&io, &mut rv);
23+
let mut parser = std::ptr::null_mut();
24+
let mut rv = mp4parse_new(&io, &mut parser);
2525
assert_eq!(rv, Mp4parseStatus::Ok);
2626
assert!(!parser.is_null());
2727

mp4parse_capi/tests/test_encryption.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ fn parse_cenc() {
2121
};
2222

2323
unsafe {
24-
let mut rv = Mp4parseStatus::Invalid;
25-
let parser = mp4parse_new(&io, &mut rv);
24+
let mut parser = std::ptr::null_mut();
25+
let mut rv = mp4parse_new(&io, &mut parser);
2626
assert_eq!(rv, Mp4parseStatus::Ok);
2727
assert!(!parser.is_null());
2828
let mut counts: u32 = 0;
@@ -104,8 +104,8 @@ fn parse_cbcs() {
104104
};
105105

106106
unsafe {
107-
let mut rv = Mp4parseStatus::Invalid;
108-
let parser = mp4parse_new(&io, &mut rv);
107+
let mut parser = std::ptr::null_mut();
108+
let mut rv = mp4parse_new(&io, &mut parser);
109109
assert_eq!(rv, Mp4parseStatus::Ok);
110110
assert!(!parser.is_null());
111111
let mut counts: u32 = 0;
@@ -166,8 +166,8 @@ fn parse_unencrypted() {
166166
};
167167

168168
unsafe {
169-
let mut rv = Mp4parseStatus::Invalid;
170-
let parser = mp4parse_new(&io, &mut rv);
169+
let mut parser = std::ptr::null_mut();
170+
let mut rv = mp4parse_new(&io, &mut parser);
171171
assert_eq!(rv, Mp4parseStatus::Ok);
172172
assert!(!parser.is_null());
173173

mp4parse_capi/tests/test_fragment.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ fn parse_fragment() {
2020
};
2121

2222
unsafe {
23-
let mut rv = Mp4parseStatus::Invalid;
24-
let parser = mp4parse_new(&io, &mut rv);
23+
let mut parser = std::ptr::null_mut();
24+
let mut rv = mp4parse_new(&io, &mut parser);
2525
assert_eq!(rv, Mp4parseStatus::Ok);
2626
assert!(!parser.is_null());
2727

@@ -73,8 +73,8 @@ fn parse_opus_fragment() {
7373
};
7474

7575
unsafe {
76-
let mut rv = Mp4parseStatus::Invalid;
77-
let parser = mp4parse_new(&io, &mut rv);
76+
let mut parser = std::ptr::null_mut();
77+
let mut rv = mp4parse_new(&io, &mut parser);
7878
assert_eq!(rv, Mp4parseStatus::Ok);
7979
assert!(!parser.is_null());
8080

mp4parse_capi/tests/test_rotation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ fn parse_rotation() {
2020
};
2121

2222
unsafe {
23-
let mut rv = Mp4parseStatus::Invalid;
24-
let parser = mp4parse_new(&io, &mut rv);
23+
let mut parser = std::ptr::null_mut();
24+
let mut rv = mp4parse_new(&io, &mut parser);
2525
assert_eq!(rv, Mp4parseStatus::Ok);
2626
assert!(!parser.is_null());
2727

0 commit comments

Comments
 (0)