Skip to content

Commit 41c260e

Browse files
committed
Use Option<extern fn()> to represent potentially-null function pointer.
This addresses https://bugzilla.mozilla.org/show_bug.cgi?id=1351497, which was filed as a rustc bug in rust-lang/rust#40913, but revealed to be undefined behaviour that happened to work with earlier compiler versions. As the comment removed in this patch describes, the only reason this code existed was to work around a limitation of rusty-cheddar.
1 parent b78dc3e commit 41c260e

File tree

5 files changed

+17
-22
lines changed

5 files changed

+17
-22
lines changed

mp4parse_capi/examples/afl-capi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn doit() {
2222
let mut input = Vec::new();
2323
std::io::stdin().read_to_end(&mut input).unwrap();
2424
let mut cursor = std::io::Cursor::new(input);
25-
let io = mp4parse_io { read: vec_read, userdata: &mut cursor as *mut _ as *mut std::os::raw::c_void };
25+
let io = mp4parse_io { read: Some(vec_read), userdata: &mut cursor as *mut _ as *mut std::os::raw::c_void };
2626
unsafe {
2727
let context = mp4parse_new(&io);
2828
let rv = mp4parse_read(context);

mp4parse_capi/src/lib.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
//!
2020
//! let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap();
2121
//! let io = mp4parse_capi::mp4parse_io {
22-
//! read: buf_read,
22+
//! read: Some(buf_read),
2323
//! userdata: &mut file as *mut _ as *mut std::os::raw::c_void
2424
//! };
2525
//! unsafe {
@@ -261,7 +261,7 @@ impl mp4parse_parser {
261261
#[repr(C)]
262262
#[derive(Clone)]
263263
pub struct mp4parse_io {
264-
pub read: extern fn(buffer: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize,
264+
pub read: Option<extern fn(buffer: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize>,
265265
pub userdata: *mut std::os::raw::c_void,
266266
}
267267

@@ -270,7 +270,7 @@ impl Read for mp4parse_io {
270270
if buf.len() > isize::max_value() as usize {
271271
return Err(std::io::Error::new(std::io::ErrorKind::Other, "buf length overflow in mp4parse_io Read impl"));
272272
}
273-
let rv = (self.read)(buf.as_mut_ptr(), buf.len(), self.userdata);
273+
let rv = self.read.unwrap()(buf.as_mut_ptr(), buf.len(), self.userdata);
274274
if rv >= 0 {
275275
Ok(rv as usize)
276276
} else {
@@ -287,12 +287,7 @@ pub unsafe extern fn mp4parse_new(io: *const mp4parse_io) -> *mut mp4parse_parse
287287
if io.is_null() || (*io).userdata.is_null() {
288288
return std::ptr::null_mut();
289289
}
290-
// is_null() isn't available on a fn type because it can't be null (in
291-
// Rust) by definition. But since this value is coming from the C API,
292-
// it *could* be null. Ideally, we'd wrap it in an Option to represent
293-
// reality, but this causes rusty-cheddar to emit the wrong type
294-
// (https://github.com/Sean1708/rusty-cheddar/issues/30).
295-
if ((*io).read as *mut std::os::raw::c_void).is_null() {
290+
if (*io).read.is_none() {
296291
return std::ptr::null_mut();
297292
}
298293
let parser = Box::new(mp4parse_parser(Wrap {
@@ -1156,7 +1151,7 @@ extern fn valid_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_v
11561151
fn new_parser() {
11571152
let mut dummy_value: u32 = 42;
11581153
let io = mp4parse_io {
1159-
read: panic_read,
1154+
read: Some(panic_read),
11601155
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
11611156
};
11621157
unsafe {
@@ -1195,19 +1190,19 @@ fn arg_validation() {
11951190
let null_mut: *mut std::os::raw::c_void = std::ptr::null_mut();
11961191

11971192
// Passing an mp4parse_io with null members is an error.
1198-
let io = mp4parse_io { read: std::mem::transmute(null_mut),
1193+
let io = mp4parse_io { read: None,
11991194
userdata: null_mut };
12001195
let parser = mp4parse_new(&io);
12011196
assert!(parser.is_null());
12021197

1203-
let io = mp4parse_io { read: panic_read,
1198+
let io = mp4parse_io { read: Some(panic_read),
12041199
userdata: null_mut };
12051200
let parser = mp4parse_new(&io);
12061201
assert!(parser.is_null());
12071202

12081203
let mut dummy_value = 42;
12091204
let io = mp4parse_io {
1210-
read: std::mem::transmute(null_mut),
1205+
read: None,
12111206
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
12121207
};
12131208
let parser = mp4parse_new(&io);
@@ -1246,7 +1241,7 @@ fn arg_validation_with_parser() {
12461241
unsafe {
12471242
let mut dummy_value = 42;
12481243
let io = mp4parse_io {
1249-
read: error_read,
1244+
read: Some(error_read),
12501245
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
12511246
};
12521247
let parser = mp4parse_new(&io);
@@ -1295,7 +1290,7 @@ fn get_track_count_poisoned_parser() {
12951290
unsafe {
12961291
let mut dummy_value = 42;
12971292
let io = mp4parse_io {
1298-
read: error_read,
1293+
read: Some(error_read),
12991294
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
13001295
};
13011296
let parser = mp4parse_new(&io);
@@ -1314,7 +1309,7 @@ fn get_track_count_poisoned_parser() {
13141309
fn arg_validation_with_data() {
13151310
unsafe {
13161311
let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap();
1317-
let io = mp4parse_io { read: valid_read,
1312+
let io = mp4parse_io { read: Some(valid_read),
13181313
userdata: &mut file as *mut _ as *mut std::os::raw::c_void };
13191314
let parser = mp4parse_new(&io);
13201315
assert!(!parser.is_null());

mp4parse_capi/tests/test_fragment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_voi
1515
fn parse_fragment() {
1616
let mut file = std::fs::File::open("tests/bipbop_audioinit.mp4").expect("Unknown file");
1717
let io = mp4parse_io {
18-
read: buf_read,
18+
read: Some(buf_read),
1919
userdata: &mut file as *mut _ as *mut std::os::raw::c_void
2020
};
2121

mp4parse_capi/tests/test_rotation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_voi
1515
fn parse_rotation() {
1616
let mut file = std::fs::File::open("tests/video_rotation_90.mp4").expect("Unknown file");
1717
let io = mp4parse_io {
18-
read: buf_read,
18+
read: Some(buf_read),
1919
userdata: &mut file as *mut _ as *mut std::os::raw::c_void
2020
};
2121

mp4parse_capi/tests/test_sample_table.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_voi
1515
fn parse_sample_table() {
1616
let mut file = std::fs::File::open("tests/bipbop_nonfragment_header.mp4").expect("Unknown file");
1717
let io = mp4parse_io {
18-
read: buf_read,
18+
read: Some(buf_read),
1919
userdata: &mut file as *mut _ as *mut std::os::raw::c_void
2020
};
2121

@@ -100,7 +100,7 @@ fn parse_sample_table() {
100100
fn parse_sample_table_with_elst() {
101101
let mut file = std::fs::File::open("tests/short-cenc.mp4").expect("Unknown file");
102102
let io = mp4parse_io {
103-
read: buf_read,
103+
read: Some(buf_read),
104104
userdata: &mut file as *mut _ as *mut std::os::raw::c_void
105105
};
106106

@@ -156,7 +156,7 @@ fn parse_sample_table_with_elst() {
156156
fn parse_sample_table_with_negative_ctts() {
157157
let mut file = std::fs::File::open("tests/white.mp4").expect("Unknown file");
158158
let io = mp4parse_io {
159-
read: buf_read,
159+
read: Some(buf_read),
160160
userdata: &mut file as *mut _ as *mut std::os::raw::c_void
161161
};
162162

0 commit comments

Comments
 (0)