-
Notifications
You must be signed in to change notification settings - Fork 722
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(bindings): make Context borrow immutable #5071
base: main
Are you sure you want to change the base?
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,14 +93,16 @@ impl Config { | |
/// Retrieve a mutable reference to the [`Context`] stored on the config. | ||
/// | ||
/// Corresponds to [s2n_config_get_ctx]. | ||
pub(crate) fn context_mut(&mut self) -> &mut Context { | ||
/// | ||
/// SAFETY: There must only ever by mutable reference to `Context` alive at | ||
/// any time. Configs can be shared across threads, so this method is | ||
/// likely not correct for your usecase. | ||
unsafe fn context_mut(&mut self) -> &mut Context { | ||
let mut ctx = core::ptr::null_mut(); | ||
unsafe { | ||
s2n_config_get_ctx(self.as_mut_ptr(), &mut ctx) | ||
.into_result() | ||
.unwrap(); | ||
&mut *(ctx as *mut Context) | ||
} | ||
s2n_config_get_ctx(self.as_mut_ptr(), &mut ctx) | ||
.into_result() | ||
.unwrap(); | ||
&mut *(ctx as *mut Context) | ||
} | ||
|
||
#[cfg(test)] | ||
|
@@ -135,7 +137,7 @@ impl Clone for Config { | |
impl Drop for Config { | ||
/// Corresponds to [s2n_config_free]. | ||
fn drop(&mut self) { | ||
let context = self.context_mut(); | ||
let context = self.context(); | ||
let count = context.refcount.fetch_sub(1, Ordering::Release); | ||
debug_assert!(count > 0, "refcount should not drop below 1 instance"); | ||
|
||
|
@@ -158,13 +160,15 @@ impl Drop for Config { | |
// https://github.com/rust-lang/rust/blob/e012a191d768adeda1ee36a99ef8b92d51920154/library/alloc/src/sync.rs#L1637 | ||
std::sync::atomic::fence(Ordering::Acquire); | ||
|
||
unsafe { | ||
// This is the last instance so free the context. | ||
let context = Box::from_raw(context); | ||
drop(context); | ||
// This is the last instance so free the context. | ||
let context = unsafe { | ||
// SAFETY: The reference count is verified to be 1, so this is the | ||
// last instance of the config, and the only reference to the context. | ||
Box::from_raw(self.context_mut()) | ||
}; | ||
drop(context); | ||
|
||
let _ = s2n_config_free(self.0.as_ptr()).into_result(); | ||
} | ||
let _ = unsafe { s2n_config_free(self.0.as_ptr()).into_result() }; | ||
} | ||
} | ||
|
||
|
@@ -334,7 +338,12 @@ impl Builder { | |
) | ||
.into_result() | ||
}; | ||
self.context_mut().application_owned_certs.push(chain); | ||
let context = unsafe { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The copy pastes are a bit tedious, but I did it this way to try and prevent anyone from passing a Practically it doesn't make a difference because the pointer isn't actually treated as |
||
// SAFETY: usage of context_mut is safe in the builder, because the | ||
// Builder owns the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.application_owned_certs.push(chain); | ||
result?; | ||
|
||
Ok(self) | ||
|
@@ -373,9 +382,12 @@ impl Builder { | |
|
||
let collected_chains = chain_arrays.into_iter().take(cert_chain_count).flatten(); | ||
|
||
self.context_mut() | ||
.application_owned_certs | ||
.extend(collected_chains); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because the | ||
// Builder owns the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.application_owned_certs.extend(collected_chains); | ||
|
||
unsafe { | ||
s2n_config_set_cert_chain_and_key_defaults( | ||
|
@@ -547,12 +559,17 @@ impl Builder { | |
verify_host(host_name, host_name_len, handler) | ||
} | ||
|
||
self.context_mut().verify_host_callback = Some(Box::new(handler)); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because the | ||
// Builder owns the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.verify_host_callback = Some(Box::new(handler)); | ||
unsafe { | ||
s2n_config_set_verify_host_callback( | ||
self.as_mut_ptr(), | ||
Some(verify_host_cb_fn), | ||
self.context_mut() as *mut Context as *mut c_void, | ||
self.config.context() as *const Context as *mut c_void, | ||
) | ||
.into_result()?; | ||
} | ||
|
@@ -607,7 +624,11 @@ impl Builder { | |
} | ||
|
||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.client_hello_callback = Some(handler); | ||
|
||
unsafe { | ||
|
@@ -628,7 +649,11 @@ impl Builder { | |
) -> Result<&mut Self, Error> { | ||
// Store callback in config context | ||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.connection_initializer = Some(handler); | ||
Ok(self) | ||
} | ||
|
@@ -659,14 +684,18 @@ impl Builder { | |
|
||
// Store callback in context | ||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.session_ticket_callback = Some(handler); | ||
|
||
unsafe { | ||
s2n_config_set_session_ticket_cb( | ||
self.as_mut_ptr(), | ||
Some(session_ticket_cb), | ||
self.context_mut() as *mut Context as *mut c_void, | ||
self.config.context() as *const Context as *mut c_void, | ||
) | ||
.into_result() | ||
}?; | ||
|
@@ -698,7 +727,11 @@ impl Builder { | |
} | ||
|
||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.private_key_callback = Some(handler); | ||
|
||
unsafe { | ||
|
@@ -734,13 +767,17 @@ impl Builder { | |
} | ||
|
||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.wall_clock = Some(handler); | ||
unsafe { | ||
s2n_config_set_wall_clock( | ||
self.as_mut_ptr(), | ||
Some(clock_cb), | ||
self.context_mut() as *mut _ as *mut c_void, | ||
self.config.context() as *const _ as *mut c_void, | ||
) | ||
.into_result()?; | ||
} | ||
|
@@ -773,13 +810,17 @@ impl Builder { | |
} | ||
|
||
let handler = Box::new(handler); | ||
let context = self.context_mut(); | ||
let context = unsafe { | ||
// SAFETY: usage of context_mut is safe in the builder, because while | ||
// it is being built, the Builder is the only reference to the config. | ||
self.config.context_mut() | ||
}; | ||
context.monotonic_clock = Some(handler); | ||
unsafe { | ||
s2n_config_set_monotonic_clock( | ||
self.as_mut_ptr(), | ||
Some(clock_cb), | ||
self.context_mut() as *mut _ as *mut c_void, | ||
self.config.context() as *const _ as *mut c_void, | ||
) | ||
.into_result()?; | ||
} | ||
|
@@ -913,17 +954,6 @@ impl Builder { | |
pub(crate) fn as_mut_ptr(&mut self) -> *mut s2n_config { | ||
self.config.as_mut_ptr() | ||
} | ||
|
||
/// Retrieve a mutable reference to the [`Context`] stored on the config. | ||
pub(crate) fn context_mut(&mut self) -> &mut Context { | ||
let mut ctx = core::ptr::null_mut(); | ||
unsafe { | ||
s2n_config_get_ctx(self.as_mut_ptr(), &mut ctx) | ||
.into_result() | ||
.unwrap(); | ||
&mut *(ctx as *mut Context) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "quic")] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove the
context_mut
method entirely? It should really only be used during the builder. If it's on the config, it's too easy to call. Or at the very least mark itunsafe
.