Skip to content

Commit 4e6919f

Browse files
committed
Use peek_callback_ctx to keep context alive during handle close
1 parent cd2ee06 commit 4e6919f

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

src/rs/lib.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,21 @@ macro_rules! define_quic_handle_ctx_fn {
702702
}
703703
}
704704

705+
/// Gets the callback context without clearing it from the handle.
706+
///
707+
/// # Safety
708+
/// Only call while closing the handle, so MsQuic will not read the
709+
/// context again after this function returns. Calling this in other
710+
/// situations can cause double frees or use-after-free.
711+
unsafe fn peek_callback_ctx(&self) -> Option<Box<Box<$callback_type>>> {
712+
let ctx = self.get_context();
713+
if ctx.is_null() {
714+
None
715+
} else {
716+
Some(Box::from_raw(ctx as *mut Box<$callback_type>))
717+
}
718+
}
719+
705720
/// Removes the callback context from the handle and returns it.
706721
///
707722
/// # Safety
@@ -927,8 +942,8 @@ impl Connection {
927942

928943
fn close_inner(&self) {
929944
if !self.handle.is_null() {
930-
// get the context and drop it after handle close.
931-
let ctx = unsafe { self.take_callback_ctx() };
945+
// Keep the context alive until ConnectionClose completes, then drop it.
946+
let ctx = unsafe { self.peek_callback_ctx() };
932947
unsafe {
933948
Api::ffi_ref().ConnectionClose.unwrap()(self.handle);
934949
}
@@ -1107,8 +1122,8 @@ impl Listener {
11071122

11081123
fn close_inner(&self) {
11091124
if !self.handle.is_null() {
1110-
// consume the context and drop it after handle close.
1111-
let ctx = unsafe { self.take_callback_ctx() };
1125+
// Keep the context alive until ListenerClose completes, then drop it.
1126+
let ctx = unsafe { self.peek_callback_ctx() };
11121127
unsafe {
11131128
Api::ffi_ref().ListenerClose.unwrap()(self.handle);
11141129
}
@@ -1184,8 +1199,8 @@ impl Stream {
11841199

11851200
pub fn close_inner(&self) {
11861201
if !self.handle.is_null() {
1187-
// consume the context and drop it after handle close.
1188-
let ctx = unsafe { self.take_callback_ctx() };
1202+
// Keep the context alive until StreamClose completes, then drop it.
1203+
let ctx = unsafe { self.peek_callback_ctx() };
11891204
unsafe {
11901205
Api::ffi_ref().StreamClose.unwrap()(self.handle);
11911206
}

0 commit comments

Comments
 (0)