From bb0676d3e23dfd7fe27f9932b955694d51438486 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Sun, 28 May 2023 20:30:55 +0200 Subject: [PATCH] fix(ext/http): fix a possible memleak in Brotli (#19250) We probably need to free the BrotliEncoderState once the stream has finished. --- ext/http/response_body.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/ext/http/response_body.rs b/ext/http/response_body.rs index 7da2142d33..6793f0e784 100644 --- a/ext/http/response_body.rs +++ b/ext/http/response_body.rs @@ -7,6 +7,7 @@ use std::pin::Pin; use std::rc::Rc; use std::task::Waker; +use brotli::ffi::compressor::BrotliEncoderState; use bytes::Bytes; use bytes::BytesMut; use deno_core::error::bad_resource; @@ -586,26 +587,42 @@ enum BrotliState { EndOfStream, } +struct BrotliEncoderStateWrapper { + stm: *mut BrotliEncoderState, +} + #[pin_project] pub struct BrotliResponseStream { state: BrotliState, - stm: *mut brotli::ffi::compressor::BrotliEncoderState, + stm: BrotliEncoderStateWrapper, current_cursor: usize, output_written_so_far: usize, #[pin] underlying: ResponseStream, } +impl Drop for BrotliEncoderStateWrapper { + fn drop(&mut self) { + // SAFETY: since we are dropping, we can be sure that this instance will not + // be used again. + unsafe { + brotli::ffi::compressor::BrotliEncoderDestroyInstance(self.stm); + } + } +} + impl BrotliResponseStream { pub fn new(underlying: ResponseStream) -> Self { Self { // SAFETY: creating an FFI instance should be OK with these args. stm: unsafe { - brotli::ffi::compressor::BrotliEncoderCreateInstance( - None, - None, - std::ptr::null_mut(), - ) + BrotliEncoderStateWrapper { + stm: brotli::ffi::compressor::BrotliEncoderCreateInstance( + None, + None, + std::ptr::null_mut(), + ), + } }, output_written_so_far: 0, current_cursor: 0, @@ -662,7 +679,7 @@ impl PollFrame for BrotliResponseStream { // SAFETY: these are okay arguments to these FFI calls. unsafe { brotli::ffi::compressor::BrotliEncoderCompressStream( - this.stm, + this.stm.stm, brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_PROCESS, &mut input_size, &input_buffer.as_ptr() as *const *const u8 as *mut *const u8, @@ -674,7 +691,7 @@ impl PollFrame for BrotliResponseStream { output_written = 0; brotli::ffi::compressor::BrotliEncoderCompressStream( - this.stm, + this.stm.stm, brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_FLUSH, &mut input_size, &input_buffer.as_ptr() as *const *const u8 as *mut *const u8, @@ -700,7 +717,7 @@ impl PollFrame for BrotliResponseStream { // SAFETY: these are okay arguments to these FFI calls. unsafe { brotli::ffi::compressor::BrotliEncoderCompressStream( - this.stm, + this.stm.stm, brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_FINISH, &mut input_size, std::ptr::null_mut(),