Skip to content

Commit

Permalink
Merge branch 'win-refactor-unsafe'
Browse files Browse the repository at this point in the history
  • Loading branch information
dlon committed Nov 7, 2024
2 parents cc1ee4f + 8d6b89b commit c2d6ead
Showing 1 changed file with 31 additions and 3 deletions.
34 changes: 31 additions & 3 deletions talpid-core/src/firewall/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,13 @@ pub extern "system" fn log_sink(
}
}

/// Convert `mb_string`, with the given character encoding `codepage`, to a UTF-16 string.
fn multibyte_to_wide(mb_string: &CStr, codepage: u32) -> Result<Vec<u16>, io::Error> {
if unsafe { *mb_string.as_ptr() } == 0 {
if mb_string.is_empty() {
return Ok(vec![]);
}

// SAFETY: `mb_string` is null-terminated and valid.
let wc_size = unsafe {
MultiByteToWideChar(
codepage,
Expand All @@ -475,8 +477,10 @@ fn multibyte_to_wide(mb_string: &CStr, codepage: u32) -> Result<Vec<u16>, io::Er
return Err(io::Error::last_os_error());
}

let mut wc_buffer = Vec::with_capacity(wc_size as usize);
let mut wc_buffer = vec![0u16; usize::try_from(wc_size).unwrap()];

// SAFETY: `wc_buffer` can contain up to `wc_size` characters, including a null
// terminator.
let chars_written = unsafe {
MultiByteToWideChar(
codepage,
Expand All @@ -492,11 +496,35 @@ fn multibyte_to_wide(mb_string: &CStr, codepage: u32) -> Result<Vec<u16>, io::Er
return Err(io::Error::last_os_error());
}

unsafe { wc_buffer.set_len((chars_written - 1) as usize) };
wc_buffer.truncate(usize::try_from(chars_written - 1).unwrap());

Ok(wc_buffer)
}

#[cfg(test)]
mod test {
use super::multibyte_to_wide;
use windows_sys::Win32::Globalization::CP_UTF8;

#[test]
fn test_multibyte_to_wide() {
// € = 0x20AC in UTF-16
let converted = multibyte_to_wide(c"€€", CP_UTF8);
const EXPECTED: &[u16] = &[0x20AC, 0x20AC];
assert!(
matches!(converted.as_deref(), Ok(EXPECTED)),
"expected Ok({EXPECTED:?}), got {converted:?}",
);

// boundary case
let converted = multibyte_to_wide(c"", CP_UTF8);
assert!(
matches!(converted.as_deref(), Ok([])),
"unexpected result {converted:?}"
);
}
}

// Convert `result` into an option and log the error, if any.
fn consume_and_log_hyperv_err<T>(
action: &'static str,
Expand Down

0 comments on commit c2d6ead

Please sign in to comment.