about summary refs log tree commit diff
path: root/library/std/src/sys_common
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys_common')
-rw-r--r--library/std/src/sys_common/backtrace.rs2
-rw-r--r--library/std/src/sys_common/mod.rs2
-rw-r--r--library/std/src/sys_common/net.rs2
-rw-r--r--library/std/src/sys_common/once/mod.rs1
-rw-r--r--library/std/src/sys_common/once/queue.rs10
-rw-r--r--library/std/src/sys_common/thread_local_key/tests.rs4
-rw-r--r--library/std/src/sys_common/wstr.rs13
-rw-r--r--library/std/src/sys_common/wtf8.rs36
-rw-r--r--library/std/src/sys_common/wtf8/tests.rs62
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);
+}