Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gracefully handle type confusion of inflate_state and tdefl_compressor in mz_stream in C API #36

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ macro_rules! oxidize {
// Make sure we catch a potential panic, as
// this is called from C.
match catch_unwind(AssertUnwindSafe(|| {
let mut stream_oxide = StreamOxide::new(&mut *stream);
let mut stream_oxide = match StreamOxide::new(&mut *stream) {
Ok(stream_oxide) => stream_oxide,
Err(e) => return e as c_int
};
let status = $mz_func_oxide(&mut stream_oxide, $($arg_name),*);
*stream = stream_oxide.into_mz_stream();
as_c_return_code(status)
Expand Down Expand Up @@ -234,7 +237,11 @@ pub unsafe extern "C" fn mz_compress2(
..Default::default()
};

let mut stream_oxide = StreamOxide::new(&mut stream);
let mut stream_oxide = match StreamOxide::new(&mut stream) {
Ok(stream_oxide) => stream_oxide,
Err(e) => return e as c_int
};

as_c_return_code(mz_compress2_oxide(&mut stream_oxide, level, dest_len))
},
)
Expand Down Expand Up @@ -272,7 +279,11 @@ pub unsafe extern "C" fn mz_uncompress(
..Default::default()
};

let mut stream_oxide = StreamOxide::new(&mut stream);
let mut stream_oxide = match StreamOxide::new(&mut stream) {
Ok(stream_oxide) => stream_oxide,
Err(e) => return e as c_int
};

as_c_return_code(mz_uncompress2_oxide(&mut stream_oxide, dest_len))
},
)
Expand Down
30 changes: 26 additions & 4 deletions src/lib_oxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,23 @@ pub unsafe extern "C" fn def_free_func(_opaque: *mut c_void, address: *mut c_voi
/// Trait used for states that can be carried by BoxedState.
pub trait StateType {
fn drop_state(&mut self);
fn get_stream_type() -> StreamType;
}
impl StateType for tdefl_compressor {
fn drop_state(&mut self) {
self.drop_inner();
}

fn get_stream_type() -> StreamType {
StreamType::Deflate
}
}
impl StateType for inflate_state {
fn drop_state(&mut self) {}

fn get_stream_type() -> StreamType {
StreamType::Inflate
}
}

/// Wrapper for a heap-allocated compressor/decompressor that frees the stucture on drop.
Expand Down Expand Up @@ -221,7 +230,13 @@ pub struct StreamOxide<'io, ST: StateType> {


impl<'io, ST: StateType> StreamOxide<'io, ST> {
pub unsafe fn new(stream: &mut mz_stream) -> Self {
pub unsafe fn new(stream: &mut mz_stream) -> Result<Self, MZError> {
if !stream.state.is_null() {
let stream_type_slice: StreamType = ptr::read(stream.state as *const StreamType);
if stream_type_slice != ST::get_stream_type() {
return Err(MZError::Stream);
}
}
let in_slice = stream.next_in.as_ref().map(|ptr| {
slice::from_raw_parts(ptr, stream.avail_in as usize)
});
Expand All @@ -230,14 +245,14 @@ impl<'io, ST: StateType> StreamOxide<'io, ST> {
slice::from_raw_parts_mut(ptr, stream.avail_out as usize)
});

StreamOxide {
Ok(StreamOxide {
next_in: in_slice,
total_in: stream.total_in,
next_out: out_slice,
total_out: stream.total_out,
state: BoxedState::new(stream),
adler: stream.adler,
}
})
}

pub fn into_mz_stream(mut self) -> mz_stream {
Expand Down Expand Up @@ -460,11 +475,17 @@ pub fn mz_deflate_reset_oxide(stream_oxide: &mut StreamOxide<tdefl_compressor>)
Ok(MZStatus::Ok)
}


#[allow(bad_style)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StreamType {
Inflate,
Deflate
}

#[repr(C)]
#[allow(bad_style)]
pub struct inflate_state {
pub stream_type: StreamType,
pub m_decomp: DecompressorOxide,

pub m_dict_ofs: c_uint,
Expand Down Expand Up @@ -495,6 +516,7 @@ pub fn mz_inflate_init2_oxide(

stream_oxide.state.alloc_state::<inflate_state>()?;
let state = stream_oxide.state.as_mut().ok_or(MZError::Mem)?;
state.stream_type = StreamType::Inflate;
state.m_decomp.init();
state.m_dict_ofs = 0;
state.m_dict_avail = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/tdef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe};

use miniz_oxide::deflate::core::{compress, compress_to_output, create_comp_flags_from_zip_params,
CompressorOxide, TDEFLFlush, TDEFLStatus};
use lib_oxide::StreamType;

/// Compression callback function type.
pub type PutBufFuncPtrNotNull = unsafe extern "C" fn(
Expand Down Expand Up @@ -44,20 +45,23 @@ pub mod strategy {
#[repr(C)]
#[allow(bad_style)]
pub struct tdefl_compressor {
pub stream_type: StreamType,
pub inner: Option<CompressorOxide>,
pub callback: Option<CallbackFunc>,
}

impl tdefl_compressor {
pub(crate) fn new(flags: u32) -> Self {
tdefl_compressor {
stream_type: StreamType::Deflate,
inner: Some(CompressorOxide::new(flags)),
callback: None,
}
}

pub(crate) fn new_with_callback(flags: u32, func: CallbackFunc) -> Self {
tdefl_compressor {
stream_type: StreamType::Deflate,
inner: Some(CompressorOxide::new(flags)),
callback: Some(func),
}
Expand Down Expand Up @@ -178,6 +182,7 @@ pub unsafe extern "C" fn tdefl_compress_buffer(
pub unsafe extern "C" fn tdefl_allocate() -> *mut tdefl_compressor {
Box::into_raw(Box::<tdefl_compressor>::new(
tdefl_compressor {
stream_type: StreamType::Deflate,
inner: None,
callback: None,
}
Expand Down