mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
fix(ext/node/ops/zlib/brotli): Allow decompressing more than 4096 bytes (#20301)
Fixes https://github.com/denoland/deno/issues/19816 In that issue, I suggest switching over the other brotli functionality to the Rust API provided by the `brotli` crate. Here, I only do that with the `brotli_decompress` function to fix the bug with buffers longer than 4096 bytes.
This commit is contained in:
parent
4a11603c76
commit
a9cc4631ca
2 changed files with 13 additions and 30 deletions
|
@ -62,6 +62,13 @@ Deno.test("brotli compression", async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test("brotli end-to-end with 4097 bytes", () => {
|
||||||
|
const a = "a".repeat(4097);
|
||||||
|
const compressed = brotliCompressSync(a);
|
||||||
|
const decompressed = brotliDecompressSync(compressed);
|
||||||
|
assertEquals(decompressed.toString(), a);
|
||||||
|
});
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
"zlib create deflate with dictionary",
|
"zlib create deflate with dictionary",
|
||||||
{ sanitizeResources: false },
|
{ sanitizeResources: false },
|
||||||
|
|
|
@ -4,6 +4,7 @@ use brotli::ffi::compressor::*;
|
||||||
use brotli::ffi::decompressor::ffi::interface::BrotliDecoderResult;
|
use brotli::ffi::decompressor::ffi::interface::BrotliDecoderResult;
|
||||||
use brotli::ffi::decompressor::ffi::BrotliDecoderState;
|
use brotli::ffi::decompressor::ffi::BrotliDecoderState;
|
||||||
use brotli::ffi::decompressor::*;
|
use brotli::ffi::decompressor::*;
|
||||||
|
use brotli::Decompressor;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op;
|
use deno_core::op;
|
||||||
|
@ -11,6 +12,7 @@ use deno_core::JsBuffer;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ToJsBuffer;
|
use deno_core::ToJsBuffer;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
|
fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
|
||||||
if mode > 6 {
|
if mode > 6 {
|
||||||
|
@ -214,36 +216,10 @@ pub fn op_brotli_compress_stream_end(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
|
fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
|
||||||
let in_buffer = buffer.as_ptr();
|
let mut output = Vec::with_capacity(4096);
|
||||||
let in_size = buffer.len();
|
let mut decompressor = Decompressor::new(buffer, buffer.len());
|
||||||
|
decompressor.read_to_end(&mut output)?;
|
||||||
let mut out = vec![0u8; 4096];
|
Ok(output.into())
|
||||||
loop {
|
|
||||||
let out_buffer = out.as_mut_ptr();
|
|
||||||
let mut out_size = out.len();
|
|
||||||
// SAFETY: TODO(littledivy)
|
|
||||||
match unsafe {
|
|
||||||
CBrotliDecoderDecompress(
|
|
||||||
in_size,
|
|
||||||
in_buffer,
|
|
||||||
&mut out_size as *mut usize,
|
|
||||||
out_buffer,
|
|
||||||
)
|
|
||||||
} {
|
|
||||||
BrotliDecoderResult::BROTLI_DECODER_RESULT_SUCCESS => {
|
|
||||||
out.truncate(out_size);
|
|
||||||
return Ok(out.into());
|
|
||||||
}
|
|
||||||
BrotliDecoderResult::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT => {
|
|
||||||
let new_size = out.len() * 2;
|
|
||||||
if new_size < out.len() {
|
|
||||||
return Err(type_error("Failed to decompress"));
|
|
||||||
}
|
|
||||||
out.resize(new_size, 0);
|
|
||||||
}
|
|
||||||
_ => return Err(type_error("Failed to decompress")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
|
|
Loading…
Reference in a new issue