diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/brotli-decompressor/src/lib.rs | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/brotli-decompressor/src/lib.rs')
-rwxr-xr-x | rust/vendor/brotli-decompressor/src/lib.rs | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/rust/vendor/brotli-decompressor/src/lib.rs b/rust/vendor/brotli-decompressor/src/lib.rs new file mode 100755 index 0000000..1dfea60 --- /dev/null +++ b/rust/vendor/brotli-decompressor/src/lib.rs @@ -0,0 +1,460 @@ +#![no_std] +#![allow(non_snake_case)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(lang_items)))] +#![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(panic_handler)))] + + +#[macro_use] +// <-- for debugging, remove xprintln from bit_reader and replace with println +#[cfg(feature="std")] +extern crate std; +#[cfg(feature="std")] +use std::io::{self, Error, ErrorKind, Read, Write}; +#[cfg(feature="std")] +extern crate alloc_stdlib; +#[macro_use] +extern crate alloc_no_stdlib as alloc; +pub use alloc::{AllocatedStackMemory, Allocator, SliceWrapper, SliceWrapperMut, StackAllocator, bzero}; +use core::ops; + +#[cfg(feature="std")] +pub use alloc_stdlib::StandardAlloc; +#[cfg(all(feature="unsafe",feature="std"))] +pub use alloc_stdlib::HeapAlloc; +#[macro_use] +mod memory; +pub mod dictionary; +mod brotli_alloc; +#[macro_use] +mod bit_reader; +mod huffman; +mod state; +mod prefix; +mod context; +pub mod transform; +mod test; +mod decode; +pub mod io_wrappers; +pub mod reader; +pub mod writer; +pub use huffman::{HuffmanCode, HuffmanTreeGroup}; +pub use state::BrotliState; +pub mod ffi; +pub use reader::{DecompressorCustomIo}; + +#[cfg(feature="std")] +pub use reader::{Decompressor}; + +pub use writer::{DecompressorWriterCustomIo}; +#[cfg(feature="std")] +pub use writer::{DecompressorWriter}; + +// use io_wrappers::write_all; +pub use io_wrappers::{CustomRead, CustomWrite}; +#[cfg(feature="std")] +pub use io_wrappers::{IntoIoReader, IoReaderWrapper, IntoIoWriter, IoWriterWrapper}; + +// interface +// pub fn BrotliDecompressStream(mut available_in: &mut usize, +// input_offset: &mut usize, +// input: &[u8], +// mut available_out: &mut usize, +// mut output_offset: &mut usize, +// mut output: &mut [u8], +// mut total_out: &mut usize, +// mut s: &mut BrotliState<AllocU8, AllocU32, AllocHC>); + +pub use decode::{BrotliDecompressStream, BrotliResult, BrotliDecoderHasMoreOutput, BrotliDecoderIsFinished, BrotliDecoderTakeOutput}; + + + + +#[cfg(not(any(feature="unsafe", not(feature="std"))))] +pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType, + w: &mut OutputType) + -> Result<(), io::Error> + where InputType: Read, + OutputType: Write +{ + let mut input_buffer: [u8; 4096] = [0; 4096]; + let mut output_buffer: [u8; 4096] = [0; 4096]; + BrotliDecompressCustomAlloc(r, + w, + &mut input_buffer[..], + &mut output_buffer[..], + StandardAlloc::default(), + StandardAlloc::default(), + StandardAlloc::default(), + ) +} + +#[cfg(feature="std")] +pub fn BrotliDecompressCustomDict<InputType, OutputType>(r: &mut InputType, + w: &mut OutputType, + input_buffer:&mut [u8], + output_buffer:&mut [u8], + custom_dictionary:std::vec::Vec<u8>) + -> Result<(), io::Error> + where InputType: Read, + OutputType: Write +{ + let mut alloc_u8 = brotli_alloc::BrotliAlloc::<u8>::new(); + let mut input_buffer_backing; + let mut output_buffer_backing; + { + let mut borrowed_input_buffer = input_buffer; + let mut borrowed_output_buffer = output_buffer; + if borrowed_input_buffer.len() == 0 { + input_buffer_backing = alloc_u8.alloc_cell(4096); + borrowed_input_buffer = input_buffer_backing.slice_mut(); + } + if borrowed_output_buffer.len() == 0 { + output_buffer_backing = alloc_u8.alloc_cell(4096); + borrowed_output_buffer = output_buffer_backing.slice_mut(); + } + let dict = alloc_u8.take_ownership(custom_dictionary); + BrotliDecompressCustomIoCustomDict(&mut IoReaderWrapper::<InputType>(r), + &mut IoWriterWrapper::<OutputType>(w), + borrowed_input_buffer, + borrowed_output_buffer, + alloc_u8, + brotli_alloc::BrotliAlloc::<u32>::new(), + brotli_alloc::BrotliAlloc::<HuffmanCode>::new(), + dict, + Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF")) + } +} + +#[cfg(all(feature="unsafe",feature="std"))] +pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType, + w: &mut OutputType) + -> Result<(), io::Error> + where InputType: Read, + OutputType: Write +{ + let mut input_buffer: [u8; 4096] = [0; 4096]; + let mut output_buffer: [u8; 4096] = [0; 4096]; + BrotliDecompressCustomAlloc(r, + w, + &mut input_buffer[..], + &mut output_buffer[..], + HeapAlloc::<u8>::new(0), + HeapAlloc::<u32>::new(0), + HeapAlloc::<HuffmanCode>::new(HuffmanCode{ bits:2, value: 1})) +} + + +#[cfg(feature="std")] +pub fn BrotliDecompressCustomAlloc<InputType, + OutputType, + AllocU8: Allocator<u8>, + AllocU32: Allocator<u32>, + AllocHC: Allocator<HuffmanCode>> + (r: &mut InputType, + w: &mut OutputType, + input_buffer: &mut [u8], + output_buffer: &mut [u8], + alloc_u8: AllocU8, + alloc_u32: AllocU32, + alloc_hc: AllocHC) + -> Result<(), io::Error> + where InputType: Read, + OutputType: Write +{ + BrotliDecompressCustomIo(&mut IoReaderWrapper::<InputType>(r), + &mut IoWriterWrapper::<OutputType>(w), + input_buffer, + output_buffer, + alloc_u8, + alloc_u32, + alloc_hc, + Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF")) +} +pub fn BrotliDecompressCustomIo<ErrType, + InputType, + OutputType, + AllocU8: Allocator<u8>, + AllocU32: Allocator<u32>, + AllocHC: Allocator<HuffmanCode>> + (r: &mut InputType, + w: &mut OutputType, + input_buffer: &mut [u8], + output_buffer: &mut [u8], + alloc_u8: AllocU8, + alloc_u32: AllocU32, + alloc_hc: AllocHC, + unexpected_eof_error_constant: ErrType) + -> Result<(), ErrType> + where InputType: CustomRead<ErrType>, + OutputType: CustomWrite<ErrType> +{ + BrotliDecompressCustomIoCustomDict(r, w, input_buffer, output_buffer, alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), unexpected_eof_error_constant) +} +pub fn BrotliDecompressCustomIoCustomDict<ErrType, + InputType, + OutputType, + AllocU8: Allocator<u8>, + AllocU32: Allocator<u32>, + AllocHC: Allocator<HuffmanCode>> + (r: &mut InputType, + w: &mut OutputType, + input_buffer: &mut [u8], + output_buffer: &mut [u8], + alloc_u8: AllocU8, + alloc_u32: AllocU32, + alloc_hc: AllocHC, + custom_dictionary: AllocU8::AllocatedMemory, + unexpected_eof_error_constant: ErrType) + -> Result<(), ErrType> + where InputType: CustomRead<ErrType>, + OutputType: CustomWrite<ErrType> +{ + let mut brotli_state = BrotliState::new_with_custom_dictionary(alloc_u8, alloc_u32, alloc_hc, custom_dictionary); + assert!(input_buffer.len() != 0); + assert!(output_buffer.len() != 0); + let mut available_out: usize = output_buffer.len(); + + let mut available_in: usize = 0; + let mut input_offset: usize = 0; + let mut output_offset: usize = 0; + let mut result: BrotliResult = BrotliResult::NeedsMoreInput; + loop { + match result { + BrotliResult::NeedsMoreInput => { + input_offset = 0; + match r.read(input_buffer) { + Err(e) => { + return Err(e); + }, + Ok(size) => { + if size == 0 { + return Err(unexpected_eof_error_constant); + } + available_in = size; + } + } + } + BrotliResult::NeedsMoreOutput => { + let mut total_written: usize = 0; + while total_written < output_offset { + // this would be a call to write_all + match w.write(&output_buffer[total_written..output_offset]) { + Err(e) => { + return Result::Err(e); + }, + Ok(cur_written) => { + assert_eq!(cur_written == 0, false); // not allowed by the contract + total_written += cur_written; + } + } + } + + output_offset = 0; + } + BrotliResult::ResultSuccess => break, + BrotliResult::ResultFailure => { + return Err(unexpected_eof_error_constant); + } + } + let mut written: usize = 0; + result = BrotliDecompressStream(&mut available_in, + &mut input_offset, + input_buffer, + &mut available_out, + &mut output_offset, + output_buffer, + &mut written, + &mut brotli_state); + + if output_offset != 0 { + let mut total_written: usize = 0; + while total_written < output_offset { + match w.write(&output_buffer[total_written..output_offset]) { + Err(e) => { + return Result::Err(e); + }, + // CustomResult::Transient(e) => continue, + Ok(cur_written) => { + assert_eq!(cur_written == 0, false); // not allowed by the contract + total_written += cur_written; + } + } + } + output_offset = 0; + available_out = output_buffer.len() + } + } + Ok(()) +} + + +#[cfg(feature="std")] +pub fn copy_from_to<R: io::Read, W: io::Write>(mut r: R, mut w: W) -> io::Result<usize> { + let mut buffer: [u8; 65536] = [0; 65536]; + let mut out_size: usize = 0; + loop { + match r.read(&mut buffer[..]) { + Err(e) => { + if let io::ErrorKind::Interrupted = e.kind() { + continue + } + return Err(e); + } + Ok(size) => { + if size == 0 { + break; + } else { + match w.write_all(&buffer[..size]) { + Err(e) => { + if let io::ErrorKind::Interrupted = e.kind() { + continue + } + return Err(e); + } + Ok(_) => out_size += size, + } + } + } + } + } + Ok(out_size) +} + +#[repr(C)] +pub struct BrotliDecoderReturnInfo { + pub decoded_size: usize, + pub error_string: [u8;256], + pub error_code: state::BrotliDecoderErrorCode, + pub result: BrotliResult, +} +impl BrotliDecoderReturnInfo { + fn new<AllocU8: Allocator<u8>, + AllocU32: Allocator<u32>, + AllocHC: Allocator<HuffmanCode>>( + state: &BrotliState<AllocU8, AllocU32, AllocHC>, + result: BrotliResult, + output_size: usize, + ) -> Self { + let mut ret = BrotliDecoderReturnInfo{ + result: result, + decoded_size: output_size, + error_code: decode::BrotliDecoderGetErrorCode(&state), + error_string: if let &Err(msg) = &state.mtf_or_error_string { + msg + } else { + [0u8;256] + }, + }; + if ret.error_string[0] == 0 { + let error_string = state::BrotliDecoderErrorStr(ret.error_code); + let to_copy = core::cmp::min(error_string.len(), ret.error_string.len() - 1); + for (dst, src) in ret.error_string[..to_copy].iter_mut().zip(error_string[..to_copy].bytes()) { + *dst = src; + } + } + ret + } +} + +declare_stack_allocator_struct!(MemPool, 512, stack); + +pub fn brotli_decode_prealloc( + input: &[u8], + mut output: &mut[u8], + scratch_u8: &mut [u8], + scratch_u32: &mut [u32], + scratch_hc: &mut [HuffmanCode], +) -> BrotliDecoderReturnInfo { + let stack_u8_allocator = MemPool::<u8>::new_allocator(scratch_u8, bzero); + let stack_u32_allocator = MemPool::<u32>::new_allocator(scratch_u32, bzero); + let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(scratch_hc, bzero); + let mut available_out = output.len(); + let mut available_in: usize = input.len(); + let mut input_offset: usize = 0; + let mut output_offset: usize = 0; + let mut written: usize = 0; + let mut brotli_state = + BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator); + let result = ::BrotliDecompressStream(&mut available_in, + &mut input_offset, + &input[..], + &mut available_out, + &mut output_offset, + &mut output, + &mut written, + &mut brotli_state); + let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); + return_info +} + +#[cfg(not(feature="std"))] +pub fn brotli_decode( + input: &[u8], + output_and_scratch: &mut[u8], +) -> BrotliDecoderReturnInfo { + let mut stack_u32_buffer = [0u32; 12 * 1024 * 6]; + let mut stack_hc_buffer = [HuffmanCode::default(); 128 * (decode::kNumInsertAndCopyCodes as usize + decode::kNumLiteralCodes as usize) + 6 * decode::kNumBlockLengthCodes as usize * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize]; + let mut guessed_output_size = core::cmp::min( + core::cmp::max(input.len(), // shouldn't shrink too much + output_and_scratch.len() / 3), + output_and_scratch.len()); + if input.len() > 2 { + let scratch_len = output_and_scratch.len() - guessed_output_size; + if let Ok(lgwin) = decode::lg_window_size(input[0], input[1]) { + let extra_window_size = 65536 + (decode::kNumLiteralCodes + decode::kNumInsertAndCopyCodes) as usize * 256 + (1usize << lgwin.0) * 5 / 4; + if extra_window_size < scratch_len { + guessed_output_size += (scratch_len - extra_window_size) * 3/4; + } + } + } + let (mut output, mut scratch_space) = output_and_scratch.split_at_mut(guessed_output_size); + let stack_u8_allocator = MemPool::<u8>::new_allocator(&mut scratch_space, bzero); + let stack_u32_allocator = MemPool::<u32>::new_allocator(&mut stack_u32_buffer, bzero); + let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(&mut stack_hc_buffer, bzero); + let mut available_out = output.len(); + let mut available_in: usize = input.len(); + let mut input_offset: usize = 0; + let mut output_offset: usize = 0; + let mut written: usize = 0; + let mut brotli_state = + BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator); + let result = ::BrotliDecompressStream(&mut available_in, + &mut input_offset, + &input[..], + &mut available_out, + &mut output_offset, + &mut output, + &mut written, + &mut brotli_state); + let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); + return_info +} + +#[cfg(feature="std")] +pub fn brotli_decode( + input: &[u8], + mut output: &mut[u8], +) -> BrotliDecoderReturnInfo { + let mut available_out = output.len(); + let mut available_in: usize = input.len(); + let mut input_offset: usize = 0; + let mut output_offset: usize = 0; + let mut written: usize = 0; + let mut brotli_state = + BrotliState::new(StandardAlloc::default(), StandardAlloc::default(), StandardAlloc::default()); + let result = ::BrotliDecompressStream(&mut available_in, + &mut input_offset, + &input[..], + &mut available_out, + &mut output_offset, + &mut output, + &mut written, + &mut brotli_state); + let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); + return_info +} |