Skip to content

Commit

Permalink
Another release candidate: this one catches panics and depends on the…
Browse files Browse the repository at this point in the history
… rust-brotli-decompressor with the bug fix for exactly 1024 bytes of random data
  • Loading branch information
danielrh committed Nov 4, 2018
1 parent e2c8c02 commit 1b87a19
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 142 deletions.
5 changes: 0 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ rust:
- nightly
- stable
- 1.12.0
- 1.8.0

os:
- linux
Expand All @@ -16,7 +15,3 @@ script:
- cargo test --no-default-features --features=std --release
- rustc --version | grep 1[.][89][.] || rustc --version | grep -v 1[.]2[789][.] | grep 1[.][12][0-9][.]||cargo build --features=validation

matrix:
exclude:
- rust: 1.8.0
os: osx
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ lto=true

[dependencies]
"alloc-no-stdlib" = {version="2.0"}
"brotli-decompressor" = {version="~2.0"}
"brotli-decompressor" = {version="> 2.0.1, < 2.1.0"}
"alloc-stdlib" = {version="~0.2", optional=true}
"packed_simd" = {version="0.3", optional=true}
"sha2" = {version="~0.8", optional=true}
Expand All @@ -41,3 +41,4 @@ disable-timer = ["brotli-decompressor/disable-timer"]
benchmark = ["brotli-decompressor/benchmark"]
vector_scratch_space = []
simd = ["packed_simd/into_bits"]
pass-through-ffi-panics = []
16 changes: 8 additions & 8 deletions c/Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
multiexample: multiexample_d decompressor multiexample.c vec_u8.h arg.h custom_alloc.h
gcc -O3 -o multiexample -g multiexample.c -I. -Ltarget/release -lbrotli -Wl,-rpath=target/release
gcc -O3 -o multiexample -g multiexample.c -I. target/release/libbrotli.[ds][lyo]*
multiexample_d: decompressor multiexample.c vec_u8.h arg.h custom_alloc.h
gcc -o multiexample_d -g multiexample.c -I. target/debug/libbrotli.[sd]?*
gcc -o multiexample_d -g multiexample.c -I. target/debug/libbrotli.[ds][lyo]*
decompressor: decompressor_d decompressor.c target/release/libbrotli.so catbrotli
gcc -O3 -o decompressor -g decompressor.c -I. -Ltarget/release -lbrotli -Wl,-rpath=target/release
gcc -O3 -o decompressor -g decompressor.c -I. target/release/libbrotli.[ds][lyo]*
decompressor_d: decompressor.c target/debug/libbrotli.so brotli_tool catbrotli_d
cargo build && gcc -o decompressor_d -g decompressor.c -I. -Ltarget/debug -lbrotli -Wl,-rpath=target/debug
cargo build && gcc -o decompressor_d -g decompressor.c -I. target/debug/libbrotli.[ds][lyo]*

brotli_tool: brotli_tool_d decompressor.c target/release/libbrotli.so
gcc -O3 -o brotli_tool -g brotli.c -I. -Ltarget/release -lbrotli -Wl,-rpath=target/release
gcc -O3 -o brotli_tool -g brotli.c -I. target/release/libbrotli.[ds][lyo]*
brotli_tool_d: decompressor.c target/debug/libbrotli.so
cargo build && gcc -o brotli_tool_d -g brotli.c -I. -Ltarget/debug -lbrotli -Wl,-rpath=target/debug
cargo build && gcc -o brotli_tool_d -g brotli.c -I. target/debug/libbrotli.[ds][lyo]*


catbrotli: catbrotli_d decompressor.c catbrotli.c target/release/libbrotli.so
gcc -O3 -o catbrotli -g catbrotli.c -I. -Ltarget/release -lbrotli -Wl,-rpath=target/release
gcc -O3 -o catbrotli -g catbrotli.c -I. target/release/libbrotli.[ds][lyo]*
catbrotli_d: catbrotli.c decompressor.c target/debug/libbrotli.so
cargo build && gcc -o catbrotli_d -g catbrotli.c -I. -Ltarget/debug -lbrotli -Wl,-rpath=target/debug
cargo build && gcc -o catbrotli_d -g catbrotli.c -I. target/debug/libbrotli.[ds][lyo]*



Expand Down
3 changes: 3 additions & 0 deletions c/multiexample.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ int32_t compress(const unsigned char *data, size_t len, struct VecU8 *ret_buffer
}
}
BrotliEncoderWorkPool *work_pool = BrotliEncoderCreateWorkPool(num_threads != 0 ? num_threads - 1 : 0, custom_malloc, custom_free, custom_alloc_opaque);
if (!work_pool) {
return 0;
}
size_t out_len = BrotliEncoderMaxCompressedSizeMulti(len, num_threads);
int32_t ret;
{
Expand Down
238 changes: 153 additions & 85 deletions src/ffi/compressor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#![cfg(not(feature="safe"))]

#[cfg(feature="std")]
use std::{panic,thread, io};
#[cfg(feature="std")]
use std::io::Write;

#[no_mangle]
use core;
use core::slice;
Expand Down Expand Up @@ -58,16 +63,19 @@ unsafe fn free_compressor_no_custom_alloc(_state_ptr: *mut BrotliEncoderState) {
}




#[no_mangle]
pub unsafe extern fn BrotliEncoderCreateInstance(
alloc_func: brotli_alloc_func,
free_func: brotli_free_func,
opaque: *mut c_void,
) -> *mut BrotliEncoderState {
match catch_panic_cstate(|| {
let allocators = CAllocator {
alloc_func:alloc_func,
free_func:free_func,
opaque:opaque,
alloc_func:alloc_func,
free_func:free_func,
opaque:opaque,
};
let to_box = BrotliEncoderState {
custom_allocator: allocators.clone(),
Expand All @@ -77,16 +85,23 @@ pub unsafe extern fn BrotliEncoderCreateInstance(
),
};
if let Some(alloc) = alloc_func {
if free_func.is_none() {
panic!("either both alloc and free must exist or neither");
}
let ptr = alloc(allocators.opaque, core::mem::size_of::<BrotliEncoderState>());
let brotli_decoder_state_ptr = core::mem::transmute::<*mut c_void, *mut BrotliEncoderState>(ptr);
core::ptr::write(brotli_decoder_state_ptr, to_box);
brotli_decoder_state_ptr
if free_func.is_none() {
panic!("either both alloc and free must exist or neither");
}
let ptr = alloc(allocators.opaque, core::mem::size_of::<BrotliEncoderState>());
let brotli_decoder_state_ptr = core::mem::transmute::<*mut c_void, *mut BrotliEncoderState>(ptr);
core::ptr::write(brotli_decoder_state_ptr, to_box);
brotli_decoder_state_ptr
} else {
brotli_new_compressor_without_custom_alloc(to_box)
brotli_new_compressor_without_custom_alloc(to_box)
}
}) {
Ok(ret) => ret,
Err(err) => {
error_print(err);
core::ptr::null_mut()
}
}
}

#[no_mangle]
Expand Down Expand Up @@ -125,13 +140,19 @@ pub unsafe extern fn BrotliEncoderHasMoreOutput(
::enc::encode::BrotliEncoderHasMoreOutput(&mut (*state_ptr).compressor)
}

#[no_mangle]
pub unsafe extern fn BrotliEncoderSetCustomDictionary(
state_ptr: &mut BrotliEncoderState,
state_ptr: *mut BrotliEncoderState,
size: usize,
dict: *const u8,
) {
let dict_slice = slice::from_raw_parts(dict, size);
::enc::encode::BrotliEncoderSetCustomDictionary(&mut (*state_ptr).compressor, size, dict_slice)
if let Err(panic_err) = catch_panic(|| {
let dict_slice = slice::from_raw_parts(dict, size);
::enc::encode::BrotliEncoderSetCustomDictionary(&mut (*state_ptr).compressor, size, dict_slice);
0
}) {
error_print(panic_err);
}
}

#[no_mangle]
Expand All @@ -158,48 +179,56 @@ pub unsafe extern fn BrotliEncoderCompress(
input_buffer: *const u8,
encoded_size: *mut usize,
encoded_buffer: *mut u8) -> i32 {
let input_buf = slice::from_raw_parts(input_buffer, input_size);
let encoded_buf = slice::from_raw_parts_mut(encoded_buffer, *encoded_size);
let allocators = CAllocator {
match catch_panic(|| {
let input_buf = slice::from_raw_parts(input_buffer, input_size);
let encoded_buf = slice::from_raw_parts_mut(encoded_buffer, *encoded_size);
let allocators = CAllocator {
alloc_func:None,
free_func:None,
opaque:core::ptr::null_mut(),
};
let translated_mode = match mode {
BrotliEncoderMode::BROTLI_MODE_GENERIC =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_GENERIC,
BrotliEncoderMode::BROTLI_MODE_TEXT =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_TEXT,
BrotliEncoderMode::BROTLI_MODE_FONT =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_FONT,
BrotliEncoderMode::BROTLI_MODE_FORCE_LSB_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_LSB_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_MSB_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_MSB_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_UTF8_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_UTF8_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_SIGNED_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_SIGNED_PRIOR,
};
let mut m8 = BrotliSubclassableAllocator::new(
SubclassableAllocator::new(allocators.clone()));
let empty_m8 = BrotliSubclassableAllocator::new(
SubclassableAllocator::new(allocators.clone()));
};
let translated_mode = match mode {
BrotliEncoderMode::BROTLI_MODE_GENERIC =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_GENERIC,
BrotliEncoderMode::BROTLI_MODE_TEXT =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_TEXT,
BrotliEncoderMode::BROTLI_MODE_FONT =>
::enc::backward_references::BrotliEncoderMode::BROTLI_MODE_FONT,
BrotliEncoderMode::BROTLI_MODE_FORCE_LSB_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_LSB_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_MSB_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_MSB_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_UTF8_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_UTF8_PRIOR,
BrotliEncoderMode::BROTLI_MODE_FORCE_SIGNED_PRIOR =>
::enc::backward_references::BrotliEncoderMode::BROTLI_FORCE_SIGNED_PRIOR,
};
let mut m8 = BrotliSubclassableAllocator::new(
SubclassableAllocator::new(allocators.clone()));
let empty_m8 = BrotliSubclassableAllocator::new(
SubclassableAllocator::new(allocators.clone()));

::enc::encode::BrotliEncoderCompress(
empty_m8,
&mut m8,
quality,
lgwin,
translated_mode,
input_size,
input_buf,
&mut *encoded_size,
encoded_buf,
&mut |_a,_b,_c,_d|(),
)
}
::enc::encode::BrotliEncoderCompress(
empty_m8,
&mut m8,
quality,
lgwin,
translated_mode,
input_size,
input_buf,
&mut *encoded_size,
encoded_buf,
&mut |_a,_b,_c,_d|(),
)

}) {
Ok(ret) => ret,
Err(panic_err) => {
error_print(panic_err);
0
},
}
}
#[no_mangle]
pub unsafe extern fn BrotliEncoderCompressStream(
state_ptr: *mut BrotliEncoderState,
Expand All @@ -209,42 +238,50 @@ pub unsafe extern fn BrotliEncoderCompressStream(
available_out: *mut usize,
output_buf_ptr: *mut*mut u8,
total_out: *mut usize) -> i32 {
let mut input_offset = 0usize;
let mut output_offset = 0usize;
let result;
let translated_op = match op {
BrotliEncoderOperation::BROTLI_OPERATION_PROCESS =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
BrotliEncoderOperation::BROTLI_OPERATION_FLUSH =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
BrotliEncoderOperation::BROTLI_OPERATION_FINISH =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
BrotliEncoderOperation::BROTLI_OPERATION_EMIT_METADATA =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_EMIT_METADATA,
};
{
let input_buf = slice::from_raw_parts(*input_buf_ptr, *available_in);
let output_buf = slice::from_raw_parts_mut(*output_buf_ptr, *available_out);
let mut to = Some(0usize);
result = ::enc::encode::BrotliEncoderCompressStream(
&mut (*state_ptr).compressor,
translated_op,
&mut *available_in,
input_buf,
&mut input_offset,
&mut *available_out,
output_buf,
&mut output_offset,
&mut to,
&mut |_a,_b,_c,_d|(),
);
if !total_out.is_null() {
*total_out = to.unwrap_or(0);
match catch_panic(|| {
let mut input_offset = 0usize;
let mut output_offset = 0usize;
let result;
let translated_op = match op {
BrotliEncoderOperation::BROTLI_OPERATION_PROCESS =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
BrotliEncoderOperation::BROTLI_OPERATION_FLUSH =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
BrotliEncoderOperation::BROTLI_OPERATION_FINISH =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
BrotliEncoderOperation::BROTLI_OPERATION_EMIT_METADATA =>
::enc::encode::BrotliEncoderOperation::BROTLI_OPERATION_EMIT_METADATA,
};
{
let input_buf = slice::from_raw_parts(*input_buf_ptr, *available_in);
let output_buf = slice::from_raw_parts_mut(*output_buf_ptr, *available_out);
let mut to = Some(0usize);
result = ::enc::encode::BrotliEncoderCompressStream(
&mut (*state_ptr).compressor,
translated_op,
&mut *available_in,
input_buf,
&mut input_offset,
&mut *available_out,
output_buf,
&mut output_offset,
&mut to,
&mut |_a,_b,_c,_d|(),
);
if !total_out.is_null() {
*total_out = to.unwrap_or(0);
}
}
*input_buf_ptr = (*input_buf_ptr).offset(input_offset as isize);
*output_buf_ptr = (*output_buf_ptr).offset(output_offset as isize);
result
}) {
Ok(ret) => ret,
Err(panic_err) => {
error_print(panic_err);
0
},
}
*input_buf_ptr = (*input_buf_ptr).offset(input_offset as isize);
*output_buf_ptr = (*output_buf_ptr).offset(output_offset as isize);
result
}


Expand Down Expand Up @@ -284,3 +321,34 @@ pub unsafe extern fn BrotliEncoderFreeUsize(state_ptr: *mut BrotliEncoderState,
}
}



#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))]
pub fn catch_panic<F:FnOnce()->i32+panic::UnwindSafe>(f: F) -> thread::Result<i32> {
panic::catch_unwind(f)
}

#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))]
fn catch_panic_cstate<F:FnOnce()->*mut BrotliEncoderState+panic::UnwindSafe>(f: F) -> thread::Result<*mut BrotliEncoderState> {
panic::catch_unwind(f)
}

#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))]
fn error_print<Err:core::fmt::Debug>(err: Err) {
let _ign = writeln!(&mut io::stderr(), "Internal Error {:?}", err);
}

// can't catch panics in a reliable way without std:: configure with panic=abort. These shouldn't happen
#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))]
pub fn catch_panic<F:FnOnce()->i32>(f: F) -> Result<i32, ()> {
Ok(f())
}

#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))]
fn catch_panic_cstate<F:FnOnce()->*mut BrotliEncoderState>(f: F) -> Result<*mut BrotliEncoderState, ()> {
Ok(f())
}

#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))]
fn error_print<Err>(_err: Err) {
}
Loading

0 comments on commit 1b87a19

Please sign in to comment.