diff options
Diffstat (limited to 'library/std/src/sys_common')
| -rw-r--r-- | library/std/src/sys_common/backtrace.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys_common/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys_common/net.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys_common/once/mod.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sys_common/once/queue.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys_common/thread_local_key/tests.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys_common/wstr.rs | 13 | ||||
| -rw-r--r-- | library/std/src/sys_common/wtf8.rs | 36 | ||||
| -rw-r--r-- | library/std/src/sys_common/wtf8/tests.rs | 62 |
9 files changed, 113 insertions, 19 deletions
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index adfe721cfa9..67711dbd5bc 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -218,7 +218,7 @@ pub fn output_filename( #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub fn set_image_base() { let image_base = crate::os::fortanix_sgx::mem::image_base(); - backtrace_rs::set_image_base(crate::ptr::invalid_mut(image_base as _)); + backtrace_rs::set_image_base(crate::ptr::without_provenance_mut(image_base as _)); } #[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))] diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 851832a377c..01f83ecb414 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -59,12 +59,14 @@ cfg_if::cfg_if! { /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInner<Inner: ?Sized> { fn as_inner(&self) -> &Inner; } /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInnerMut<Inner: ?Sized> { fn as_inner_mut(&mut self) -> &mut Inner; } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 8712bd2eca7..de7d31baaaf 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -199,7 +199,7 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> { init(); - run_with_cstr(host.as_bytes(), |c_host| { + run_with_cstr(host.as_bytes(), &|c_host| { let mut hints: c::addrinfo = unsafe { mem::zeroed() }; hints.ai_socktype = c::SOCK_STREAM; let mut res = ptr::null_mut(); diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys_common/once/mod.rs index 359697d8313..ec57568c54c 100644 --- a/library/std/src/sys_common/once/mod.rs +++ b/library/std/src/sys_common/once/mod.rs @@ -25,6 +25,7 @@ cfg_if::cfg_if! { target_family = "unix", all(target_vendor = "fortanix", target_env = "sgx"), target_os = "solid_asp3", + target_os = "xous", ))] { mod queue; pub use queue::{Once, OnceState}; diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys_common/once/queue.rs index def0bcd6fac..3cc1df113e3 100644 --- a/library/std/src/sys_common/once/queue.rs +++ b/library/std/src/sys_common/once/queue.rs @@ -110,7 +110,7 @@ impl Once { #[inline] #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")] pub const fn new() -> Once { - Once { state_and_queue: AtomicPtr::new(ptr::invalid_mut(INCOMPLETE)) } + Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) } } #[inline] @@ -158,7 +158,7 @@ impl Once { // Try to register this thread as the one RUNNING. let exchange_result = self.state_and_queue.compare_exchange( state_and_queue, - ptr::invalid_mut(RUNNING), + ptr::without_provenance_mut(RUNNING), Ordering::Acquire, Ordering::Acquire, ); @@ -170,14 +170,14 @@ impl Once { // wake them up on drop. let mut waiter_queue = WaiterQueue { state_and_queue: &self.state_and_queue, - set_state_on_drop_to: ptr::invalid_mut(POISONED), + set_state_on_drop_to: ptr::without_provenance_mut(POISONED), }; // Run the initialization function, letting it know if we're // poisoned or not. let init_state = public::OnceState { inner: OnceState { poisoned: state_and_queue.addr() == POISONED, - set_state_on_drop_to: Cell::new(ptr::invalid_mut(COMPLETE)), + set_state_on_drop_to: Cell::new(ptr::without_provenance_mut(COMPLETE)), }, }; init(&init_state); @@ -289,6 +289,6 @@ impl OnceState { #[inline] pub fn poison(&self) { - self.set_state_on_drop_to.set(ptr::invalid_mut(POISONED)); + self.set_state_on_drop_to.set(ptr::without_provenance_mut(POISONED)); } } diff --git a/library/std/src/sys_common/thread_local_key/tests.rs b/library/std/src/sys_common/thread_local_key/tests.rs index 6a44c65d918..48bed31af51 100644 --- a/library/std/src/sys_common/thread_local_key/tests.rs +++ b/library/std/src/sys_common/thread_local_key/tests.rs @@ -9,8 +9,8 @@ fn statik() { unsafe { assert!(K1.get().is_null()); assert!(K2.get().is_null()); - K1.set(ptr::invalid_mut(1)); - K2.set(ptr::invalid_mut(2)); + K1.set(ptr::without_provenance_mut(1)); + K2.set(ptr::without_provenance_mut(2)); assert_eq!(K1.get() as usize, 1); assert_eq!(K2.get() as usize, 2); } diff --git a/library/std/src/sys_common/wstr.rs b/library/std/src/sys_common/wstr.rs index b230fd1a829..8eae1606485 100644 --- a/library/std/src/sys_common/wstr.rs +++ b/library/std/src/sys_common/wstr.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] use crate::marker::PhantomData; -use crate::num::NonZeroU16; +use crate::num::NonZero; use crate::ptr::NonNull; /// A safe iterator over a LPWSTR @@ -23,15 +23,15 @@ impl WStrUnits<'_> { Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData }) } - pub fn peek(&self) -> Option<NonZeroU16> { + pub fn peek(&self) -> Option<NonZero<u16>> { // SAFETY: It's always safe to read the current item because we don't // ever move out of the array's bounds. - unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) } + unsafe { NonZero::new(*self.lpwstr.as_ptr()) } } /// Advance the iterator while `predicate` returns true. /// Returns the number of items it advanced by. - pub fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize { + pub fn advance_while<P: FnMut(NonZero<u16>) -> bool>(&mut self, mut predicate: P) -> usize { let mut counter = 0; while let Some(w) = self.peek() { if !predicate(w) { @@ -46,8 +46,9 @@ impl WStrUnits<'_> { impl Iterator for WStrUnits<'_> { // This can never return zero as that marks the end of the string. - type Item = NonZeroU16; - fn next(&mut self) -> Option<NonZeroU16> { + type Item = NonZero<u16>; + + fn next(&mut self) -> Option<Self::Item> { // SAFETY: If NULL is reached we immediately return. // Therefore it's safe to advance the pointer after that. unsafe { diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 67db5ebd89c..2dbd19d7171 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -885,15 +885,43 @@ fn decode_surrogate_pair(lead: u16, trail: u16) -> char { unsafe { char::from_u32_unchecked(code_point) } } -/// Copied from core::str::StrPrelude::is_char_boundary +/// Copied from str::is_char_boundary #[inline] pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool { - if index == slice.len() { + if index == 0 { return true; } match slice.bytes.get(index) { - None => false, - Some(&b) => b < 128 || b >= 192, + None => index == slice.len(), + Some(&b) => (b as i8) >= -0x40, + } +} + +/// Verify that `index` is at the edge of either a valid UTF-8 codepoint +/// (i.e. a codepoint that's not a surrogate) or of the whole string. +/// +/// These are the cases currently permitted by `OsStr::slice_encoded_bytes`. +/// Splitting between surrogates is valid as far as WTF-8 is concerned, but +/// we do not permit it in the public API because WTF-8 is considered an +/// implementation detail. +#[track_caller] +#[inline] +pub fn check_utf8_boundary(slice: &Wtf8, index: usize) { + if index == 0 { + return; + } + match slice.bytes.get(index) { + Some(0xED) => (), // Might be a surrogate + Some(&b) if (b as i8) >= -0x40 => return, + Some(_) => panic!("byte index {index} is not a codepoint boundary"), + None if index == slice.len() => return, + None => panic!("byte index {index} is out of bounds"), + } + if slice.bytes[index + 1] >= 0xA0 { + // There's a surrogate after index. Now check before index. + if index >= 3 && slice.bytes[index - 3] == 0xED && slice.bytes[index - 2] >= 0xA0 { + panic!("byte index {index} lies between surrogate codepoints"); + } } } diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index 28a426648e5..6a1cc41a8fb 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -663,3 +663,65 @@ fn wtf8_to_owned() { assert_eq!(string.bytes, b"\xED\xA0\x80"); assert!(!string.is_known_utf8); } + +#[test] +fn wtf8_valid_utf8_boundaries() { + let mut string = Wtf8Buf::from_str("aé 💩"); + string.push(CodePoint::from_u32(0xD800).unwrap()); + string.push(CodePoint::from_u32(0xD800).unwrap()); + check_utf8_boundary(&string, 0); + check_utf8_boundary(&string, 1); + check_utf8_boundary(&string, 3); + check_utf8_boundary(&string, 4); + check_utf8_boundary(&string, 8); + check_utf8_boundary(&string, 14); + assert_eq!(string.len(), 14); + + string.push_char('a'); + check_utf8_boundary(&string, 14); + check_utf8_boundary(&string, 15); + + let mut string = Wtf8Buf::from_str("a"); + string.push(CodePoint::from_u32(0xD800).unwrap()); + check_utf8_boundary(&string, 1); + + let mut string = Wtf8Buf::from_str("\u{D7FF}"); + string.push(CodePoint::from_u32(0xD800).unwrap()); + check_utf8_boundary(&string, 3); + + let mut string = Wtf8Buf::new(); + string.push(CodePoint::from_u32(0xD800).unwrap()); + string.push_char('\u{D7FF}'); + check_utf8_boundary(&string, 3); +} + +#[test] +#[should_panic(expected = "byte index 4 is out of bounds")] +fn wtf8_utf8_boundary_out_of_bounds() { + let string = Wtf8::from_str("aé"); + check_utf8_boundary(&string, 4); +} + +#[test] +#[should_panic(expected = "byte index 1 is not a codepoint boundary")] +fn wtf8_utf8_boundary_inside_codepoint() { + let string = Wtf8::from_str("é"); + check_utf8_boundary(&string, 1); +} + +#[test] +#[should_panic(expected = "byte index 1 is not a codepoint boundary")] +fn wtf8_utf8_boundary_inside_surrogate() { + let mut string = Wtf8Buf::new(); + string.push(CodePoint::from_u32(0xD800).unwrap()); + check_utf8_boundary(&string, 1); +} + +#[test] +#[should_panic(expected = "byte index 3 lies between surrogate codepoints")] +fn wtf8_utf8_boundary_between_surrogates() { + let mut string = Wtf8Buf::new(); + string.push(CodePoint::from_u32(0xD800).unwrap()); + string.push(CodePoint::from_u32(0xD800).unwrap()); + check_utf8_boundary(&string, 3); +} |
