Skip to content

Commit 2f595d9

Browse files
authored
Merge pull request #81 from kinetiknz/bug1351497
Fix UB caused by casting a Rust fn ptr to a *c_void (BMO bug #1351497)
2 parents 92476e5 + 596bedb commit 2f595d9

File tree

6 files changed

+18
-23
lines changed

6 files changed

+18
-23
lines changed

mp4parse_capi/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ mp4parse = {version = "0.7.1", path = "../mp4parse"}
2929
num-traits = "0.1.37"
3030

3131
[build-dependencies]
32-
rusty-cheddar = "0.3.2"
32+
rusty-cheddar = { git = "https://github.com/kinetiknz/rusty-cheddar" }
3333

3434
[features]
3535
fuzz = ["mp4parse/fuzz"]

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 {
@@ -1136,7 +1131,7 @@ extern fn valid_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_v
11361131
fn new_parser() {
11371132
let mut dummy_value: u32 = 42;
11381133
let io = mp4parse_io {
1139-
read: panic_read,
1134+
read: Some(panic_read),
11401135
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
11411136
};
11421137
unsafe {
@@ -1175,19 +1170,19 @@ fn arg_validation() {
11751170
let null_mut: *mut std::os::raw::c_void = std::ptr::null_mut();
11761171

11771172
// Passing an mp4parse_io with null members is an error.
1178-
let io = mp4parse_io { read: std::mem::transmute(null_mut),
1173+
let io = mp4parse_io { read: None,
11791174
userdata: null_mut };
11801175
let parser = mp4parse_new(&io);
11811176
assert!(parser.is_null());
11821177

1183-
let io = mp4parse_io { read: panic_read,
1178+
let io = mp4parse_io { read: Some(panic_read),
11841179
userdata: null_mut };
11851180
let parser = mp4parse_new(&io);
11861181
assert!(parser.is_null());
11871182

11881183
let mut dummy_value = 42;
11891184
let io = mp4parse_io {
1190-
read: std::mem::transmute(null_mut),
1185+
read: None,
11911186
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
11921187
};
11931188
let parser = mp4parse_new(&io);
@@ -1226,7 +1221,7 @@ fn arg_validation_with_parser() {
12261221
unsafe {
12271222
let mut dummy_value = 42;
12281223
let io = mp4parse_io {
1229-
read: error_read,
1224+
read: Some(error_read),
12301225
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
12311226
};
12321227
let parser = mp4parse_new(&io);
@@ -1275,7 +1270,7 @@ fn get_track_count_poisoned_parser() {
12751270
unsafe {
12761271
let mut dummy_value = 42;
12771272
let io = mp4parse_io {
1278-
read: error_read,
1273+
read: Some(error_read),
12791274
userdata: &mut dummy_value as *mut _ as *mut std::os::raw::c_void,
12801275
};
12811276
let parser = mp4parse_new(&io);
@@ -1294,7 +1289,7 @@ fn get_track_count_poisoned_parser() {
12941289
fn arg_validation_with_data() {
12951290
unsafe {
12961291
let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap();
1297-
let io = mp4parse_io { read: valid_read,
1292+
let io = mp4parse_io { read: Some(valid_read),
12981293
userdata: &mut file as *mut _ as *mut std::os::raw::c_void };
12991294
let parser = mp4parse_new(&io);
13001295
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)