diff --git a/Cargo.toml b/Cargo.toml index 0c7c2725..f46608fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brotli" -version = "3.0.2" +version = "3.0.3" authors = ["Daniel Reiter Horn ", "The Brotli Authors"] description = "A brotli compressor and decompressor that with an interface avoiding the rust stdlib. This makes it suitable for embedded devices and kernels. It is designed with a pluggable allocator so that the standard lib's allocator may be employed. The default build also includes a stdlib allocator and stream interface. Disable this with --features=no-stdlib. All included code is safe." license = "BSD-3-Clause/MIT" @@ -26,7 +26,7 @@ lto=true [dependencies] "alloc-no-stdlib" = {version="2.0"} -"brotli-decompressor" = {version="~2.0", default-features=false} +"brotli-decompressor" = {version="~2.1", default-features=false} "alloc-stdlib" = {version="~0.2", optional=true} "packed_simd" = {version="0.3", optional=true} "sha2" = {version="~0.8", optional=true} diff --git a/c/Cargo.toml b/c/Cargo.toml index d4e08de9..a650b059 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brotli-ffi" -version = "1.0.0" +version = "1.0.1" authors = ["Daniel Reiter Horn ", "The Brotli Authors"] description = "A brotli compressor and decompressor that with an interface exactly matching https://github.com/google/brotli. All included code is safe except the thin exported C-compatible functions." license = "BSD-3-Clause/MIT" @@ -19,7 +19,7 @@ crate-type=["cdylib", "staticlib", "rlib"] lto=true [dependencies] -"brotli" = {version="~3.0", default-features=false, path="../"} +"brotli" = {version="~3.0", default-features=false} [features] validation=["brotli/validation"] diff --git a/c/go/interface_test.go b/c/go/interface_test.go index 47f5fef8..0755ab1f 100644 --- a/c/go/interface_test.go +++ b/c/go/interface_test.go @@ -151,22 +151,19 @@ func TestCompressRoundtripZero(*testing.T) { Appendable: true, Magic: true, } + compressedForm := bytes.NewBuffer(nil) writer := brotli.NewMultiCompressionWriter( - brotli.NewDecompressionWriter( + io.MultiWriter(compressedForm, brotli.NewDecompressionWriter( outBuffer, ), + ), options, ) - _, err := writer.Write(data) - + err := writer.Close() if err != nil { panic(err) } - err = writer.Close() - if err != nil { - panic(err) - } - if len(outBuffer.Bytes()) == 0 { + if len(compressedForm.Bytes()) == 0 { panic("Zero output buffer") } if !bytes.Equal(outBuffer.Bytes(), data[:]) { @@ -240,17 +237,20 @@ func TestCompressReaderRoundtripZero(*testing.T) { Appendable: true, Magic: true, } + compressedForm := bytes.NewBuffer(nil) reader := brotli.NewDecompressionReader( + io.TeeReader( brotli.NewMultiCompressionReader( inBuffer, options, ), + compressedForm), ) _, err := io.Copy(outBuffer, reader) if err != nil { panic(err) } - if len(outBuffer.Bytes()) == 0 { + if len(compressedForm.Bytes()) == 0 { panic("Zero output buffer") } if !bytes.Equal(outBuffer.Bytes(), data[:]) { diff --git a/c/go/main.go b/c/go/main.go index a51ca0fd..7a8622db 100644 --- a/c/go/main.go +++ b/c/go/main.go @@ -14,7 +14,7 @@ func main() { Quality: 9.5, Catable: true, Appendable: true, - Magic: true, + Magic: false, } useWriter := false var toCat []string diff --git a/src/ffi/broccoli.rs b/src/ffi/broccoli.rs index 9221d057..8a616b01 100644 --- a/src/ffi/broccoli.rs +++ b/src/ffi/broccoli.rs @@ -1,7 +1,10 @@ use core; -use core::slice; pub use brotli_decompressor::ffi::interface::{ - c_void, + c_void +}; +use brotli_decompressor::ffi::{ + slice_from_raw_parts_or_nil, + slice_from_raw_parts_or_nil_mut, }; use concat::BroCatli; pub use concat::BroCatliResult; @@ -75,8 +78,8 @@ pub unsafe extern fn BroccoliConcatStream( input_buf_ptr: *mut*const u8, available_out: *mut usize, output_buf_ptr: *mut*mut u8) -> BroccoliResult { - 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 input_buf = slice_from_raw_parts_or_nil(*input_buf_ptr, *available_in); + let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out); let mut input_offset = 0usize; let mut output_offset = 0usize; let mut bro_catli: BroCatli = (*state).into(); @@ -94,7 +97,7 @@ pub unsafe extern fn BroccoliConcatFinish( state: *mut BroccoliState, available_out: *mut usize, output_buf_ptr: *mut*mut u8) -> BroCatliResult { - let output_buf = slice::from_raw_parts_mut(*output_buf_ptr, *available_out); + let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out); let mut output_offset = 0usize; let mut bro_catli: BroCatli = (*state).into(); let ret = bro_catli.finish(output_buf, &mut output_offset); diff --git a/src/ffi/compressor.rs b/src/ffi/compressor.rs index d914a7e3..d7d0880f 100755 --- a/src/ffi/compressor.rs +++ b/src/ffi/compressor.rs @@ -7,10 +7,18 @@ use std::io::Write; #[no_mangle] use core; -use core::slice; use brotli_decompressor::ffi::alloc_util; use brotli_decompressor::ffi::alloc_util::SubclassableAllocator; -use brotli_decompressor::ffi::interface::{brotli_alloc_func, brotli_free_func, CAllocator, c_void}; +use brotli_decompressor::ffi::interface::{ + brotli_alloc_func, + brotli_free_func, + CAllocator, + c_void, +}; +use brotli_decompressor::ffi::{ + slice_from_raw_parts_or_nil, + slice_from_raw_parts_or_nil_mut, +}; use ::enc::encode::BrotliEncoderStateStruct; use super::alloc_util::BrotliSubclassableAllocator; @@ -147,7 +155,7 @@ pub unsafe extern fn BrotliEncoderSetCustomDictionary( dict: *const u8, ) { if let Err(panic_err) = catch_panic(|| { - let dict_slice = slice::from_raw_parts(dict, size); + let dict_slice = slice_from_raw_parts_or_nil(dict, size); ::enc::encode::BrotliEncoderSetCustomDictionary(&mut (*state_ptr).compressor, size, dict_slice); 0 }) { @@ -180,8 +188,8 @@ pub unsafe extern fn BrotliEncoderCompress( encoded_size: *mut usize, encoded_buffer: *mut u8) -> i32 { 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 input_buf = slice_from_raw_parts_or_nil(input_buffer, input_size); + let encoded_buf = slice_from_raw_parts_or_nil_mut(encoded_buffer, *encoded_size); let allocators = CAllocator { alloc_func:None, free_func:None, @@ -253,8 +261,8 @@ pub unsafe extern fn BrotliEncoderCompressStream( ::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 input_buf = slice_from_raw_parts_or_nil(*input_buf_ptr, *available_in); + let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out); let mut to = Some(0usize); result = ::enc::encode::BrotliEncoderCompressStream( &mut (*state_ptr).compressor, diff --git a/src/ffi/multicompress/mod.rs b/src/ffi/multicompress/mod.rs index 3150115d..ba7055ba 100755 --- a/src/ffi/multicompress/mod.rs +++ b/src/ffi/multicompress/mod.rs @@ -6,12 +6,21 @@ use std::io::Write; mod test; #[no_mangle] use core; -use core::slice; #[allow(unused_imports)] use brotli_decompressor; use super::compressor; use brotli_decompressor::ffi::alloc_util::SubclassableAllocator; -use brotli_decompressor::ffi::interface::{brotli_alloc_func, brotli_free_func, CAllocator, c_void}; +use brotli_decompressor::ffi::interface::{ + brotli_alloc_func, + brotli_free_func, + CAllocator, + c_void, +}; +use brotli_decompressor::ffi::{ + slice_from_raw_parts_or_nil, + slice_from_raw_parts_or_nil_mut, +}; + use super::alloc_util::BrotliSubclassableAllocator; use ::enc; use ::enc::backward_references::BrotliEncoderParams; @@ -62,10 +71,10 @@ pub unsafe extern fn BrotliEncoderCompressMulti( let alloc_opaque = if alloc_opaque_per_thread.is_null() { &null_opaques[..] } else { - slice::from_raw_parts(alloc_opaque_per_thread, desired_num_threads) + slice_from_raw_parts_or_nil(alloc_opaque_per_thread, desired_num_threads) }; - let param_keys_slice = slice::from_raw_parts(param_keys, num_params); - let param_values_slice = slice::from_raw_parts(param_values, num_params); + let param_keys_slice = slice_from_raw_parts_or_nil(param_keys, num_params); + let param_values_slice = slice_from_raw_parts_or_nil(param_values, num_params); let mut params = BrotliEncoderParams::default(); for (k,v) in param_keys_slice.iter().zip(param_values_slice.iter()) { if set_parameter(&mut params, *k, *v) == 0 { @@ -93,8 +102,8 @@ pub unsafe extern fn BrotliEncoderCompressMulti( ]; let res = enc::compress_multi_no_threadpool( ¶ms, - &mut Owned::new(SliceRef(slice::from_raw_parts(input, input_size))), - slice::from_raw_parts_mut(encoded, *encoded_size), + &mut Owned::new(SliceRef(slice_from_raw_parts_or_nil(input, input_size))), + slice_from_raw_parts_or_nil_mut(encoded, *encoded_size), &mut alloc_array[..num_threads], ); match res { @@ -239,10 +248,10 @@ pub unsafe extern fn BrotliEncoderCompressWorkPool( let alloc_opaque = if alloc_opaque_per_thread.is_null() { &null_opaques[..] } else { - slice::from_raw_parts(alloc_opaque_per_thread, desired_num_threads) + slice_from_raw_parts_or_nil(alloc_opaque_per_thread, desired_num_threads) }; - let param_keys_slice = slice::from_raw_parts(param_keys, num_params); - let param_values_slice = slice::from_raw_parts(param_values, num_params); + let param_keys_slice = slice_from_raw_parts_or_nil(param_keys, num_params); + let param_values_slice = slice_from_raw_parts_or_nil(param_values, num_params); let mut params = BrotliEncoderParams::default(); for (k,v) in param_keys_slice.iter().zip(param_values_slice.iter()) { if set_parameter(&mut params, *k, *v) == 0 { @@ -270,8 +279,8 @@ pub unsafe extern fn BrotliEncoderCompressWorkPool( ]; let res = enc::compress_worker_pool( ¶ms, - &mut Owned::new(SliceRef(slice::from_raw_parts(input, input_size))), - slice::from_raw_parts_mut(encoded, *encoded_size), + &mut Owned::new(SliceRef(slice_from_raw_parts_or_nil(input, input_size))), + slice_from_raw_parts_or_nil_mut(encoded, *encoded_size), &mut alloc_array[..num_threads], &mut (*work_pool_wrapper.0).work_pool, ); diff --git a/src/ffi/multicompress/test.rs b/src/ffi/multicompress/test.rs index c8704e16..e358a8e2 100755 --- a/src/ffi/multicompress/test.rs +++ b/src/ffi/multicompress/test.rs @@ -128,6 +128,43 @@ fn test_compress_empty_multi_raw() { assert_eq!(&rt_buffer[..rt_size], &input[..]); } +#[test] +fn test_compress_null_multi_raw() { + let params = [BrotliEncoderParameter::BROTLI_PARAM_QUALITY, BrotliEncoderParameter::BROTLI_PARAM_LGWIN, BrotliEncoderParameter::BROTLI_PARAM_SIZE_HINT, BrotliEncoderParameter::BROTLI_PARAM_CATABLE, BrotliEncoderParameter::BROTLI_PARAM_MAGIC_NUMBER, BrotliEncoderParameter::BROTLI_PARAM_Q9_5]; + let values = [3u32,16u32,0u32,0u32,0u32,0u32]; + let mut encoded_size = BrotliEncoderMaxCompressedSizeMulti(0, 4); + let mut encoded_backing = [0u8;145]; + let encoded = &mut encoded_backing[..encoded_size]; + let ret = unsafe { + BrotliEncoderCompressMulti( + params.len(), + params[..].as_ptr(), + values[..].as_ptr(), + 0, + core::ptr::null(), + &mut encoded_size, + encoded.as_mut_ptr(), + 4, + None, + None, + core::ptr::null_mut()) + }; + assert_eq!(ret, 1); + let mut rt_size = 256; + let mut rt_buffer = [0u8;256]; + assert!(encoded_size != 0); + let ret2 = unsafe { + super::super::decompressor::CBrotliDecoderDecompress(encoded_size, encoded.as_ptr(), + &mut rt_size, rt_buffer.as_mut_ptr()) + }; + match ret2 { + super::super::decompressor::ffi::interface::BrotliDecoderResult::BROTLI_DECODER_RESULT_SUCCESS => { + }, + _ => panic!(ret2), + } + assert_eq!(rt_size, 0); +} + #[test]