diff options
| author | Sebastian Holmin <sebastian.holmin@mullvad.net> | 2025-07-10 09:32:20 +0200 |
|---|---|---|
| committer | Sebastian Holmin <sebastian.holmin@mullvad.net> | 2025-07-10 09:32:20 +0200 |
| commit | 2cdb3c216a5ff3e0a12224666339f4444d2e18b8 (patch) | |
| tree | 9c5e7e9e839a58ae5eecf56e656b0353ff1565a3 | |
| parent | 4d90ff4fd81b0692945df0c67e0e8074716c14f3 (diff) | |
| parent | 7259eabc670ef78a2ab6029cd99f6708ac6f2754 (diff) | |
| download | mullvadvpn-2cdb3c216a5ff3e0a12224666339f4444d2e18b8.tar.xz mullvadvpn-2cdb3c216a5ff3e0a12224666339f4444d2e18b8.zip | |
Merge branch 'fix-rust-warnings-prepare-2024-edition'
21 files changed, 178 insertions, 134 deletions
diff --git a/android/translations-converter/src/android/string_value.rs b/android/translations-converter/src/android/string_value.rs index 31c753e3cf..1880d5f757 100644 --- a/android/translations-converter/src/android/string_value.rs +++ b/android/translations-converter/src/android/string_value.rs @@ -155,8 +155,8 @@ mod tests { fn newline_collapsing() { let input = StringValue::from_unescaped( "This is - a multi-line string - that should be + a multi-line string + that should be collapsed into a single line", None, ); @@ -217,7 +217,7 @@ mod tests { } let serialized_input = r#"<root>A multi-line string value - with \"quotes\" and + with \"quotes\" and parameters %2$s %d %1$d</root>"#; let deserialized: Wrapper = diff --git a/mullvad-ios/src/api_client/access_method_settings.rs b/mullvad-ios/src/api_client/access_method_settings.rs index 2870047e24..40f0acd714 100644 --- a/mullvad-ios/src/api_client/access_method_settings.rs +++ b/mullvad-ios/src/api_client/access_method_settings.rs @@ -143,7 +143,7 @@ pub unsafe extern "C" fn init_access_method_settings_wrapper( ) }; - let custom = access_methods_from_raw_array(custom_methods_raw, custom_method_count); + let custom = unsafe { access_methods_from_raw_array(custom_methods_raw, custom_method_count) }; let settings = Settings::new(direct, mullvad_bridges, encrypted_dns_proxy, custom); let context = SwiftAccessMethodSettingsContext { settings }; SwiftAccessMethodSettingsWrapper::new(context) @@ -177,7 +177,7 @@ impl SwiftAccessMethodSettingsWrapper { } pub unsafe fn into_rust_context(self) -> Box<SwiftAccessMethodSettingsContext> { - Box::from_raw(self.0) + unsafe { Box::from_raw(self.0) } } } diff --git a/mullvad-ios/src/api_client/account.rs b/mullvad-ios/src/api_client/account.rs index 227e81ba30..eb755f3191 100644 --- a/mullvad-ios/src/api_client/account.rs +++ b/mullvad-ios/src/api_client/account.rs @@ -30,14 +30,15 @@ use super::{ /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_get_account( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, account_number: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -86,13 +87,14 @@ pub unsafe extern "C" fn mullvad_ios_get_account( /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_create_account( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -132,14 +134,15 @@ pub unsafe extern "C" fn mullvad_ios_create_account( /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_delete_account( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, account_number: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); diff --git a/mullvad-ios/src/api_client/address_cache_provider.rs b/mullvad-ios/src/api_client/address_cache_provider.rs index 9d5f656c62..0458ae2fe3 100644 --- a/mullvad-ios/src/api_client/address_cache_provider.rs +++ b/mullvad-ios/src/api_client/address_cache_provider.rs @@ -3,7 +3,7 @@ use std::{ffi::c_void, net::SocketAddr}; use super::get_string; -extern "C" { +unsafe extern "C" { /// Return the latest available endpoint, or a default one if none are cached /// /// # SAFETY diff --git a/mullvad-ios/src/api_client/api.rs b/mullvad-ios/src/api_client/api.rs index 14c36bc595..20fe2ba248 100644 --- a/mullvad-ios/src/api_client/api.rs +++ b/mullvad-ios/src/api_client/api.rs @@ -30,13 +30,14 @@ use super::{ /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_get_addresses( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -74,14 +75,15 @@ pub unsafe extern "C" fn mullvad_ios_get_addresses( /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_api_addrs_available( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, access_method_setting: *const c_void, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -148,14 +150,15 @@ pub unsafe extern "C" fn mullvad_ios_api_addrs_available( /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_get_relays( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, etag: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); diff --git a/mullvad-ios/src/api_client/cancellation.rs b/mullvad-ios/src/api_client/cancellation.rs index 4c86919e2d..eea57b6a0a 100644 --- a/mullvad-ios/src/api_client/cancellation.rs +++ b/mullvad-ios/src/api_client/cancellation.rs @@ -62,7 +62,7 @@ impl RequestCancelHandle { /// # Safety /// /// `handle_ptr` must be pointing to a valid instance of `SwiftCancelHandle`. -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn mullvad_api_cancel_task(handle_ptr: &mut SwiftCancelHandle) { if handle_ptr.ptr.is_null() { return; @@ -79,7 +79,7 @@ extern "C" fn mullvad_api_cancel_task(handle_ptr: &mut SwiftCancelHandle) { /// # Safety /// /// `handle_ptr` must be pointing to a valid instance of `SwiftCancelHandle`. -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn mullvad_api_cancel_task_drop(handle_ptr: &mut SwiftCancelHandle) { if handle_ptr.ptr.is_null() { return; diff --git a/mullvad-ios/src/api_client/completion.rs b/mullvad-ios/src/api_client/completion.rs index 7689ad0f6a..aa1a00bb07 100644 --- a/mullvad-ios/src/api_client/completion.rs +++ b/mullvad-ios/src/api_client/completion.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; use super::response::SwiftMullvadApiResponse; -extern "C" { +unsafe extern "C" { /// Maps to `mullvadApiCompletionFinish` on Swift side to facilitate callback based completion flow when doing /// network calls through Mullvad API on Rust side. /// diff --git a/mullvad-ios/src/api_client/device.rs b/mullvad-ios/src/api_client/device.rs index 6a6ee1b07e..e0eb44fa9f 100644 --- a/mullvad-ios/src/api_client/device.rs +++ b/mullvad-ios/src/api_client/device.rs @@ -42,7 +42,8 @@ pub unsafe extern "C" fn mullvad_ios_get_device( account_number: *const c_char, identifier: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -52,8 +53,8 @@ pub unsafe extern "C" fn mullvad_ios_get_device( let api_context = api_context.rust_context(); // Safety: The caller must guarantee that `retry_strategy` is not null and has not been freed let retry_strategy = unsafe { retry_strategy.into_rust() }; - let account_number = get_string(account_number); - let identifier = get_string(identifier); + let account_number = unsafe { get_string(account_number) }; + let identifier = unsafe { get_string(identifier) }; let completion = completion_handler.clone(); let task = tokio_handle.spawn(async move { @@ -100,7 +101,8 @@ pub unsafe extern "C" fn mullvad_ios_get_devices( retry_strategy: SwiftRetryStrategy, account_number: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -110,7 +112,7 @@ pub unsafe extern "C" fn mullvad_ios_get_devices( let api_context = api_context.rust_context(); // Safety: The caller must guarantee that `retry_strategy` is not null and has not been freed let retry_strategy = unsafe { retry_strategy.into_rust() }; - let account_number = get_string(account_number); + let account_number = unsafe { get_string(account_number) }; let completion = completion_handler.clone(); let task = tokio_handle.spawn(async move { @@ -158,7 +160,8 @@ pub unsafe extern "C" fn mullvad_ios_create_device( account_number: *const c_char, public_key: *const u8, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -168,7 +171,7 @@ pub unsafe extern "C" fn mullvad_ios_create_device( let api_context = api_context.rust_context(); // Safety: The caller must guarantee that `retry_strategy` is not null and has not been freed let retry_strategy = unsafe { retry_strategy.into_rust() }; - let account_number = get_string(account_number); + let account_number = unsafe { get_string(account_number) }; // Safety: `public_key` pointer must be a valid pointer to 32 unsigned bytes. let pub_key: [u8; 32] = unsafe { ptr::read(public_key as *const [u8; 32]) }; @@ -218,7 +221,8 @@ pub unsafe extern "C" fn mullvad_ios_delete_device( account_number: *const c_char, identifier: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -228,8 +232,8 @@ pub unsafe extern "C" fn mullvad_ios_delete_device( let api_context = api_context.rust_context(); // Safety: The caller must guarantee that `retry_strategy` is not null and has not been freed let retry_strategy = unsafe { retry_strategy.into_rust() }; - let account_number = get_string(account_number); - let identifier = get_string(identifier); + let account_number = unsafe { get_string(account_number) }; + let identifier = unsafe { get_string(identifier) }; let completion = completion_handler.clone(); let task = tokio_handle.spawn(async move { @@ -279,7 +283,8 @@ pub unsafe extern "C" fn mullvad_ios_rotate_device_key( identifier: *const c_char, public_key: *const u8, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -289,8 +294,8 @@ pub unsafe extern "C" fn mullvad_ios_rotate_device_key( let api_context = api_context.rust_context(); // Safety: The caller must guarantee that `retry_strategy` is not null and has not been freed let retry_strategy = unsafe { retry_strategy.into_rust() }; - let account_number = get_string(account_number); - let identifier = get_string(identifier); + let account_number = unsafe { get_string(account_number) }; + let identifier = unsafe { get_string(identifier) }; // Safety: `public_key` pointer must be a valid pointer to 32 unsigned bytes. let pub_key: [u8; 32] = unsafe { ptr::read(public_key as *const [u8; 32]) }; diff --git a/mullvad-ios/src/api_client/helpers.rs b/mullvad-ios/src/api_client/helpers.rs index 556b679d71..e363c5862c 100644 --- a/mullvad-ios/src/api_client/helpers.rs +++ b/mullvad-ios/src/api_client/helpers.rs @@ -46,14 +46,15 @@ pub unsafe extern "C" fn new_shadowsocks_access_method_setting( c_password: *const c_char, c_cipher: *const c_char, ) -> *const c_void { - let endpoint: SocketAddr = if let Some(ip_address) = parse_ip_addr(address, address_len) { - SocketAddr::new(ip_address, port) - } else { - return std::ptr::null(); - }; + let endpoint: SocketAddr = + if let Some(ip_address) = unsafe { parse_ip_addr(address, address_len) } { + SocketAddr::new(ip_address, port) + } else { + return std::ptr::null(); + }; - let password = get_string(c_password); - let cipher = get_string(c_cipher); + let password = unsafe { get_string(c_password) }; + let cipher = unsafe { get_string(c_cipher) }; let shadowsocks_configuration = Shadowsocks { endpoint, @@ -79,18 +80,19 @@ pub unsafe extern "C" fn new_socks5_access_method_setting( c_username: *const c_char, c_password: *const c_char, ) -> *const c_void { - let endpoint: SocketAddr = if let Some(ip_address) = parse_ip_addr(address, address_len) { - SocketAddr::new(ip_address, port) - } else { - return std::ptr::null(); - }; + let endpoint: SocketAddr = + if let Some(ip_address) = unsafe { parse_ip_addr(address, address_len) } { + SocketAddr::new(ip_address, port) + } else { + return std::ptr::null(); + }; let auth = { if c_username.is_null() || c_password.is_null() { None } else { - let username = get_string(c_username); - let password = get_string(c_password); + let username = unsafe { get_string(c_username) }; + let password = unsafe { get_string(c_password) }; SocksAuth::new(username, password).ok() } }; diff --git a/mullvad-ios/src/api_client/mod.rs b/mullvad-ios/src/api_client/mod.rs index 1c45fb3397..82535d0e40 100644 --- a/mullvad-ios/src/api_client/mod.rs +++ b/mullvad-ios/src/api_client/mod.rs @@ -91,7 +91,7 @@ pub unsafe extern "C" fn mullvad_api_update_access_methods( api_context: SwiftApiContext, settings_wrapper: SwiftAccessMethodSettingsWrapper, ) { - let access_methods = settings_wrapper.into_rust_context().settings; + let access_methods = unsafe { settings_wrapper.into_rust_context().settings }; api_context .rust_context() .update_access_methods(access_methods); @@ -109,7 +109,7 @@ pub unsafe extern "C" fn mullvad_api_use_access_method( ) { let api_context = api_context.rust_context(); // SAFETY: See Safety notes for `get_string` - let id = get_string(access_method_id); + let id = unsafe { get_string(access_method_id) }; let Some(id) = Id::from_string(id) else { return; @@ -130,7 +130,7 @@ pub unsafe extern "C" fn mullvad_api_use_access_method( /// /// This function is safe. #[cfg(feature = "api-override")] -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn mullvad_api_init_new_tls_disabled( host: *const c_char, address: *const c_char, @@ -162,7 +162,7 @@ pub extern "C" fn mullvad_api_init_new_tls_disabled( /// to proceed in a meaningful way anyway. /// /// This function is safe. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn mullvad_api_init_new( host: *const c_char, address: *const c_char, diff --git a/mullvad-ios/src/api_client/problem_report.rs b/mullvad-ios/src/api_client/problem_report.rs index 652d27550e..06101b86f7 100644 --- a/mullvad-ios/src/api_client/problem_report.rs +++ b/mullvad-ios/src/api_client/problem_report.rs @@ -42,7 +42,8 @@ pub unsafe extern "C" fn mullvad_ios_send_problem_report( retry_strategy: SwiftRetryStrategy, request: SwiftProblemReportRequest, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let completion = completion_handler.clone(); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { @@ -122,9 +123,9 @@ struct ProblemReportRequest { impl ProblemReportRequest { // SAFETY: the members of `SwiftProblemReportRequest` must point to null-terminated strings unsafe fn from_swift_parameters(request: SwiftProblemReportRequest) -> Option<Self> { - let address = get_string(request.address); - let message = get_string(request.message); - let log = get_string(request.log).into(); + let address = unsafe { get_string(request.address) }; + let message = unsafe { get_string(request.message) }; + let log = unsafe { get_string(request.log) }.into(); let metadata = if request.metadata.inner.is_null() { BTreeMap::new() @@ -132,7 +133,7 @@ impl ProblemReportRequest { let swift_map = &request.metadata; let mut converted_map = BTreeMap::new(); - if let Some(inner) = swift_map.inner.as_ref() { + if let Some(inner) = unsafe { swift_map.inner.as_ref() } { for (key, value) in &inner.0 { converted_map.insert(key.clone(), value.clone()); } @@ -199,7 +200,7 @@ impl Map { } } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn swift_problem_report_metadata_new() -> ProblemReportMetadata { let map = Box::new(Map::new()); ProblemReportMetadata { @@ -230,7 +231,7 @@ pub unsafe extern "C" fn swift_problem_report_metadata_add( } } -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn swift_problem_report_metadata_free(map: ProblemReportMetadata) { if !map.inner.is_null() { // SAFETY: `map.inner` must be properly aligned and non-null diff --git a/mullvad-ios/src/api_client/response.rs b/mullvad-ios/src/api_client/response.rs index 4871a5d4bf..df7795b0c2 100644 --- a/mullvad-ios/src/api_client/response.rs +++ b/mullvad-ios/src/api_client/response.rs @@ -142,21 +142,23 @@ impl SwiftMullvadApiResponse { /// /// `response` must be pointing to a valid instance of `SwiftMullvadApiResponse`. This function /// is not safe to call multiple times with the same `SwiftMullvadApiResponse`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_response_drop(response: SwiftMullvadApiResponse) { - if !response.body.is_null() { - let _ = Vec::from_raw_parts(response.body, response.body_size, response.body_size); - } + unsafe { + if !response.body.is_null() { + let _ = Vec::from_raw_parts(response.body, response.body_size, response.body_size); + } - if !response.etag.is_null() { - let _ = CString::from_raw(response.etag); - } + if !response.etag.is_null() { + let _ = CString::from_raw(response.etag); + } - if !response.error_description.is_null() { - let _ = CString::from_raw(response.error_description); - } + if !response.error_description.is_null() { + let _ = CString::from_raw(response.error_description); + } - if !response.server_response_code.is_null() { - let _ = CString::from_raw(response.server_response_code); + if !response.server_response_code.is_null() { + let _ = CString::from_raw(response.server_response_code); + } } } diff --git a/mullvad-ios/src/api_client/retry_strategy.rs b/mullvad-ios/src/api_client/retry_strategy.rs index 80a3b9668c..06b9aa94db 100644 --- a/mullvad-ios/src/api_client/retry_strategy.rs +++ b/mullvad-ios/src/api_client/retry_strategy.rs @@ -9,7 +9,7 @@ impl SwiftRetryStrategy { /// # Safety /// The pointer must be a pointing to a valid instance of a `Box<RetryStrategy>`. pub unsafe fn into_rust(self) -> RetryStrategy { - *Box::from_raw(self.0) + unsafe { *Box::from_raw(self.0) } } } @@ -46,7 +46,7 @@ pub enum RetryDelay { /// Creates a retry strategy that never retries after failure. /// The result needs to be consumed. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn mullvad_api_retry_strategy_never() -> SwiftRetryStrategy { let retry_strategy = RetryStrategy { delays: RetryDelay::Never, @@ -59,7 +59,7 @@ pub extern "C" fn mullvad_api_retry_strategy_never() -> SwiftRetryStrategy { /// Creates a retry strategy that retries `max_retries` times with a constant delay of `delay_sec`. /// The result needs to be consumed. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn mullvad_api_retry_strategy_constant( max_retries: usize, delay_sec: u64, @@ -77,7 +77,7 @@ pub extern "C" fn mullvad_api_retry_strategy_constant( /// Creates a retry strategy that retries `max_retries` times with a exponantially increating delay. /// The delay will never exceed `max_delay_sec` /// The result needs to be consumed. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn mullvad_api_retry_strategy_exponential( max_retries: usize, initial_sec: u64, diff --git a/mullvad-ios/src/api_client/shadowsocks_loader.rs b/mullvad-ios/src/api_client/shadowsocks_loader.rs index 161ee8a30a..2d63b179d3 100644 --- a/mullvad-ios/src/api_client/shadowsocks_loader.rs +++ b/mullvad-ios/src/api_client/shadowsocks_loader.rs @@ -1,7 +1,7 @@ use std::ffi::c_void; use talpid_types::net::proxy::Shadowsocks; -extern "C" { +unsafe extern "C" { /// Creates a `Shadowsocks` configuration. /// /// # SAFETY diff --git a/mullvad-ios/src/api_client/storekit.rs b/mullvad-ios/src/api_client/storekit.rs index 994e6628d7..f5e149b7a4 100644 --- a/mullvad-ios/src/api_client/storekit.rs +++ b/mullvad-ios/src/api_client/storekit.rs @@ -34,7 +34,7 @@ use super::{ /// `body_size` must be the size of the body /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_legacy_storekit_payment( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, @@ -43,7 +43,8 @@ pub unsafe extern "C" fn mullvad_ios_legacy_storekit_payment( body: *const u8, body_size: usize, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -57,7 +58,7 @@ pub unsafe extern "C" fn mullvad_ios_legacy_storekit_payment( let completion = completion_handler.clone(); // SAFETY: See param documentation for `account_number`. - let account_number = AccountNumber::from(get_string(account_number)); + let account_number = AccountNumber::from(unsafe { get_string(account_number) }); // SAFETY: See param documentation for `body`. let body = unsafe { std::slice::from_raw_parts(body, body_size) }.to_vec(); @@ -110,14 +111,15 @@ async fn mullvad_ios_legacy_storekit_payment_inner( /// `mullvad_api_retry_strategy_never`, `mullvad_api_retry_strategy_constant` or `mullvad_api_retry_strategy_exponential` /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_init_storekit_payment( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, retry_strategy: SwiftRetryStrategy, account_number: *const c_char, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -132,7 +134,7 @@ pub unsafe extern "C" fn mullvad_ios_init_storekit_payment( let completion = completion_handler.clone(); // SAFETY: See param documentation for `account_number`. - let account_number = AccountNumber::from(get_string(account_number)); + let account_number = AccountNumber::from(unsafe { get_string(account_number) }); let task = tokio_handle.spawn(async move { match mullvad_ios_init_storekit_payment_inner( @@ -184,7 +186,7 @@ async fn mullvad_ios_init_storekit_payment_inner( /// `body_size` must be the size of the body /// /// This function is not safe to call multiple times with the same `CompletionCookie`. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn mullvad_ios_check_storekit_payment( api_context: SwiftApiContext, completion_cookie: *mut libc::c_void, @@ -193,7 +195,8 @@ pub unsafe extern "C" fn mullvad_ios_check_storekit_payment( body: *const u8, body_size: usize, ) -> SwiftCancelHandle { - let completion_handler = SwiftCompletionHandler::new(CompletionCookie::new(completion_cookie)); + let completion_handler = + SwiftCompletionHandler::new(unsafe { CompletionCookie::new(completion_cookie) }); let Ok(tokio_handle) = crate::mullvad_ios_runtime() else { completion_handler.finish(SwiftMullvadApiResponse::no_tokio_runtime()); @@ -207,7 +210,7 @@ pub unsafe extern "C" fn mullvad_ios_check_storekit_payment( let completion = completion_handler.clone(); // SAFETY: See param documentation for `account_number`. - let account_number = AccountNumber::from(get_string(account_number)); + let account_number = AccountNumber::from(unsafe { get_string(account_number) }); // SAFETY: See param documentation for `body`. let body = unsafe { std::slice::from_raw_parts(body, body_size) }.to_vec(); diff --git a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs index 9942c78f62..e0fc9420aa 100644 --- a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs +++ b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs @@ -94,7 +94,7 @@ impl Drop for DaitaParameters { } } -extern "C" { +unsafe extern "C" { /// To be called when ephemeral peer exchange has finished. All parameters except /// `raw_packet_tunnel` are optional. /// diff --git a/mullvad-ios/src/lib.rs b/mullvad-ios/src/lib.rs index b98960f158..305e044fd5 100644 --- a/mullvad-ios/src/lib.rs +++ b/mullvad-ios/src/lib.rs @@ -1,4 +1,5 @@ #![cfg(target_os = "ios")] +#![allow(clippy::undocumented_unsafe_blocks)] use libc::c_char; use std::ffi::CStr; use std::sync::OnceLock; diff --git a/mullvad-ios/src/shadowsocks_proxy/ffi.rs b/mullvad-ios/src/shadowsocks_proxy/ffi.rs index 815862fb52..cf038d6933 100644 --- a/mullvad-ios/src/shadowsocks_proxy/ffi.rs +++ b/mullvad-ios/src/shadowsocks_proxy/ffi.rs @@ -35,16 +35,17 @@ pub unsafe extern "C" fn start_shadowsocks_proxy( .init(); }); - let forward_ip = - if let Some(forward_address) = { parse_ip_addr(forward_address, forward_address_len) } { - forward_address - } else { - return -1; - }; + let forward_ip = if let Some(forward_address) = + { unsafe { parse_ip_addr(forward_address, forward_address_len) } } + { + forward_address + } else { + return -1; + }; let forward_socket_addr = SocketAddr::new(forward_ip, forward_port); - let bridge_ip = if let Some(addr) = { parse_ip_addr(addr, addr_len) } { + let bridge_ip = if let Some(addr) = { unsafe { parse_ip_addr(addr, addr_len) } } { addr } else { return -1; diff --git a/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs b/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs index 849d4336cc..50ac53d3be 100644 --- a/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs +++ b/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs @@ -26,14 +26,11 @@ pub unsafe extern "C" fn start_udp2tcp_obfuscator_proxy( ) -> i32 { init_logging(); - let peer_sock_addr = throw_int_error!(get_socket_address( - peer_address, - peer_address_len, - peer_port - )); + let peer_sock_addr = + throw_int_error!(unsafe { get_socket_address(peer_address, peer_address_len, peer_port) }); let result = TunnelObfuscatorRuntime::new_udp2tcp(peer_sock_addr).run(); - start(proxy_handle, result) + unsafe { start(proxy_handle, result) } } #[unsafe(no_mangle)] @@ -45,14 +42,11 @@ pub unsafe extern "C" fn start_shadowsocks_obfuscator_proxy( ) -> i32 { init_logging(); - let peer_sock_addr = throw_int_error!(get_socket_address( - peer_address, - peer_address_len, - peer_port - )); + let peer_sock_addr = + throw_int_error!(unsafe { get_socket_address(peer_address, peer_address_len, peer_port) }); let result = TunnelObfuscatorRuntime::new_shadowsocks(peer_sock_addr).run(); - start(proxy_handle, result) + unsafe { start(proxy_handle, result) } } #[unsafe(no_mangle)] @@ -66,16 +60,13 @@ pub unsafe extern "C" fn start_quic_obfuscator_proxy( ) -> i32 { init_logging(); - let peer_sock_addr = throw_int_error!(get_socket_address( - peer_address, - peer_address_len, - peer_port - )); - let hostname = get_string(hostname); - let token = get_string(token); + let peer_sock_addr = + throw_int_error!(unsafe { get_socket_address(peer_address, peer_address_len, peer_port) }); + let hostname = unsafe { get_string(hostname) }; + let token = unsafe { get_string(token) }; let result = TunnelObfuscatorRuntime::new_quic(peer_sock_addr, hostname, token).run(); - start(proxy_handle, result) + unsafe { start(proxy_handle, result) } } fn init_logging() { diff --git a/mullvad-nsis/src/lib.rs b/mullvad-nsis/src/lib.rs index e47436da5d..5aed1389c0 100644 --- a/mullvad-nsis/src/lib.rs +++ b/mullvad-nsis/src/lib.rs @@ -21,7 +21,10 @@ pub enum Status { /// Max path size allowed const MAX_PATH_SIZE: isize = 32_767; -/// SAFETY: path needs to be a windows path encoded as a string of u16 that terminates in 0 (two +/// Creates a privileged directory at the specified Windows path. +/// +/// # SAFETY +/// path needs to be a windows path encoded as a string of u16 that terminates in 0 (two /// nul-bytes). The string is also not allowed to be greater than `MAX_PATH_SIZE`. #[unsafe(no_mangle)] pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status { @@ -29,14 +32,18 @@ pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status let mut i = 0; // Calculate the length of the path by checking when the first u16 == 0 let len = loop { - if *(path.offset(i)) == 0 { + // SAFETY: We assume that `path` is a valid pointer to a u16 array, + // ending with a null terminator. + if unsafe { *(path.offset(i)) } == 0 { break i; } else if i >= MAX_PATH_SIZE { return Status::InvalidArguments; } i += 1; }; - let path = std::slice::from_raw_parts(path, len as usize); + // SAFETY: Because we checked the length, we can safely create a slice + // from the raw pointer. + let path = unsafe { std::slice::from_raw_parts(path, len as usize) }; let path = OsString::from_wide(path); let path = Path::new(&path); @@ -52,6 +59,10 @@ pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status /// is returned, and the required buffer size (in chars) is returned in `buffer_size`. /// On success, `buffer_size` is set to the length of the string, including /// the final null terminator. +/// +/// # SAFETY +/// if `buffer` is not null, it must point to a valid memory location that can hold +/// at least `buffer_size` number of `u16` values. #[unsafe(no_mangle)] pub unsafe extern "C" fn get_system_local_appdata( buffer: *mut u16, @@ -72,15 +83,20 @@ pub unsafe extern "C" fn get_system_local_appdata( let path = path.as_os_str(); let path_u16: Vec<u16> = path.encode_wide().chain(std::iter::once(0u16)).collect(); - let prev_len = *buffer_size; + // SAFETY: `buffer_size` is non-null because we checked it above. + unsafe { + let prev_len = *buffer_size; + *buffer_size = path_u16.len(); - *buffer_size = path_u16.len(); - - if prev_len < path_u16.len() || buffer.is_null() { - return Status::InsufficientBufferSize; + if prev_len < path_u16.len() || buffer.is_null() { + return Status::InsufficientBufferSize; + } } - ptr::copy_nonoverlapping(path_u16.as_ptr(), buffer, path_u16.len()); + // SAFETY: We assume that `buffer` is a valid pointer to a u16 array + // and because of the previous check, we know that `buffer` has enough space + // to hold the contents of `path_u16`. + unsafe { ptr::copy_nonoverlapping(path_u16.as_ptr(), buffer, path_u16.len()) }; Status::Ok }) @@ -91,6 +107,10 @@ pub unsafe extern "C" fn get_system_local_appdata( /// `InsufficientBufferSize` is returned, and the required buffer size (in /// chars) is returned in `buffer_size`. On success, `buffer_size` is set to the /// length of the string, including the final null terminator. +/// +/// # Safety +/// If `buffer` is not null, it must point to a valid memory location that can hold +/// at least `*buffer_size` number of `u16` values. `buffer_size` must be a valid pointer. #[unsafe(no_mangle)] pub unsafe extern "C" fn get_system_version(buffer: *mut u16, buffer_size: *mut usize) -> Status { use talpid_platform_metadata::version; @@ -105,13 +125,19 @@ pub unsafe extern "C" fn get_system_version(buffer: *mut u16, buffer_size: *mut .chain(iter::once(0u16)) .collect(); - if *buffer_size < build_number.len() || buffer.is_null() { - return Status::InsufficientBufferSize; - } + // SAFETY: `buffer_size` is non-null because we checked it above. + unsafe { + if *buffer_size < build_number.len() || buffer.is_null() { + return Status::InsufficientBufferSize; + } - *buffer_size = build_number.len(); + *buffer_size = build_number.len(); + } - ptr::copy_nonoverlapping(build_number.as_ptr(), buffer, build_number.len()); + // SAFETY: We assume that `buffer` is a valid pointer to a u16 array + // and because of the previous check, we know that `buffer` has enough space + // to hold the contents of `build_number`. + unsafe { ptr::copy_nonoverlapping(build_number.as_ptr(), buffer, build_number.len()) }; Status::Ok }) } diff --git a/mullvad-types/src/auth_failed.rs b/mullvad-types/src/auth_failed.rs index 335f8463f3..a86540eca6 100644 --- a/mullvad-types/src/auth_failed.rs +++ b/mullvad-types/src/auth_failed.rs @@ -79,13 +79,19 @@ mod tests { #[test] fn test_parsing() { - let tests = vec![ - (Some("INVALID_ACCOUNT"), - "[INVALID_ACCOUNT] This is not a valid Mullvad account"), - (Some("EXPIRED_ACCOUNT"), - "[EXPIRED_ACCOUNT] This account has no time left"), - (Some("TOO_MANY_CONNECTIONS"), - "[TOO_MANY_CONNECTIONS] This Mullvad account is already used by the maximum number of simultaneous connections"), + let tests = [ + ( + Some("INVALID_ACCOUNT"), + "[INVALID_ACCOUNT] This is not a valid Mullvad account", + ), + ( + Some("EXPIRED_ACCOUNT"), + "[EXPIRED_ACCOUNT] This account has no time left", + ), + ( + Some("TOO_MANY_CONNECTIONS"), + "[TOO_MANY_CONNECTIONS] This Mullvad account is already used by the maximum number of simultaneous connections", + ), (None, "[Incomplete String"), (Some("REASON_REASON"), "[REASON_REASON]"), (Some("REASON_REASON"), "[REASON_REASON]A"), |
