]> git.proxmox.com Git - rustc.git/blame - library/std/src/sys/sgx/abi/usercalls/alloc.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / std / src / sys / sgx / abi / usercalls / alloc.rs
CommitLineData
0731742a
XL
1#![allow(unused)]
2
532ac7d7 3use crate::cell::UnsafeCell;
60c5eb7d
XL
4use crate::mem;
5use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
6use crate::ptr::{self, NonNull};
532ac7d7 7use crate::slice;
532ac7d7 8use crate::slice::SliceIndex;
0731742a 9
0731742a 10use super::super::mem::is_user_range;
60c5eb7d 11use fortanix_sgx_abi::*;
0731742a
XL
12
13/// A type that can be safely read from or written to userspace.
14///
15/// Non-exhaustive list of specific requirements for reading and writing:
16/// * **Type is `Copy`** (and therefore also not `Drop`). Copies will be
17/// created when copying from/to userspace. Destructors will not be called.
18/// * **No references or Rust-style owned pointers** (`Vec`, `Arc`, etc.). When
19/// reading from userspace, references into enclave memory must not be
20/// created. Also, only enclave memory is considered managed by the Rust
21/// compiler's static analysis. When reading from userspace, there can be no
22/// guarantee that the value correctly adheres to the expectations of the
23/// type. When writing to userspace, memory addresses of data in enclave
24/// memory must not be leaked for confidentiality reasons. `User` and
25/// `UserRef` are also not allowed for the same reasons.
26/// * **No fat pointers.** When reading from userspace, the size or vtable
27/// pointer could be automatically interpreted and used by the code. When
28/// writing to userspace, memory addresses of data in enclave memory (such
29/// as vtable pointers) must not be leaked for confidentiality reasons.
30///
31/// Non-exhaustive list of specific requirements for reading from userspace:
32/// * **Any bit pattern is valid** for this type (no `enum`s). There can be no
33/// guarantee that the value correctly adheres to the expectations of the
34/// type, so any value must be valid for this type.
35///
36/// Non-exhaustive list of specific requirements for writing to userspace:
37/// * **No pointers to enclave memory.** Memory addresses of data in enclave
38/// memory must not be leaked for confidentiality reasons.
39/// * **No internal padding.** Padding might contain previously-initialized
40/// secret data stored at that memory location and must not be leaked for
41/// confidentiality reasons.
42#[unstable(feature = "sgx_platform", issue = "56975")]
43pub unsafe trait UserSafeSized: Copy + Sized {}
44
45#[unstable(feature = "sgx_platform", issue = "56975")]
46unsafe impl UserSafeSized for u8 {}
47#[unstable(feature = "sgx_platform", issue = "56975")]
48unsafe impl<T> UserSafeSized for FifoDescriptor<T> {}
49#[unstable(feature = "sgx_platform", issue = "56975")]
50unsafe impl UserSafeSized for ByteBuffer {}
51#[unstable(feature = "sgx_platform", issue = "56975")]
52unsafe impl UserSafeSized for Usercall {}
53#[unstable(feature = "sgx_platform", issue = "56975")]
54unsafe impl UserSafeSized for Return {}
55#[unstable(feature = "sgx_platform", issue = "56975")]
56unsafe impl<T: UserSafeSized> UserSafeSized for [T; 2] {}
57
58/// A type that can be represented in memory as one or more `UserSafeSized`s.
59#[unstable(feature = "sgx_platform", issue = "56975")]
60pub unsafe trait UserSafe {
61 /// Equivalent to `mem::align_of::<Self>`.
62 fn align_of() -> usize;
63
64 /// Construct a pointer to `Self` given a memory range in user space.
65 ///
9fa01778 66 /// N.B., this takes a size, not a length!
0731742a
XL
67 ///
68 /// # Safety
9fa01778 69 ///
0731742a
XL
70 /// The caller must ensure the memory range is in user memory, is the
71 /// correct size and is correctly aligned and points to the right type.
72 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self;
73
74 /// Construct a pointer to `Self` given a memory range.
75 ///
9fa01778 76 /// N.B., this takes a size, not a length!
0731742a
XL
77 ///
78 /// # Safety
9fa01778 79 ///
0731742a
XL
80 /// The caller must ensure the memory range points to the correct type.
81 ///
82 /// # Panics
9fa01778 83 ///
0731742a
XL
84 /// This function panics if:
85 ///
9fa01778
XL
86 /// * the pointer is not aligned.
87 /// * the pointer is null.
48663c56 88 /// * the pointed-to range does not fit in the address space.
9fa01778 89 /// * the pointed-to range is not in user memory.
0731742a 90 unsafe fn from_raw_sized(ptr: *mut u8, size: usize) -> NonNull<Self> {
48663c56 91 assert!(ptr.wrapping_add(size) >= ptr);
29967ef6
XL
92 // SAFETY: The caller has guaranteed the pointer is valid
93 let ret = unsafe { Self::from_raw_sized_unchecked(ptr, size) };
94 unsafe {
95 Self::check_ptr(ret);
96 NonNull::new_unchecked(ret as _)
97 }
0731742a
XL
98 }
99
9fa01778 100 /// Checks if a pointer may point to `Self` in user memory.
0731742a
XL
101 ///
102 /// # Safety
9fa01778 103 ///
0731742a
XL
104 /// The caller must ensure the memory range points to the correct type and
105 /// length (if this is a slice).
106 ///
107 /// # Panics
9fa01778 108 ///
0731742a
XL
109 /// This function panics if:
110 ///
9fa01778
XL
111 /// * the pointer is not aligned.
112 /// * the pointer is null.
113 /// * the pointed-to range is not in user memory.
0731742a 114 unsafe fn check_ptr(ptr: *const Self) {
60c5eb7d 115 let is_aligned = |p| -> bool { 0 == (p as usize) & (Self::align_of() - 1) };
0731742a
XL
116
117 assert!(is_aligned(ptr as *const u8));
29967ef6 118 assert!(is_user_range(ptr as _, mem::size_of_val(unsafe { &*ptr })));
0731742a
XL
119 assert!(!ptr.is_null());
120 }
121}
122
123#[unstable(feature = "sgx_platform", issue = "56975")]
124unsafe impl<T: UserSafeSized> UserSafe for T {
125 fn align_of() -> usize {
126 mem::align_of::<T>()
127 }
128
129 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
130 assert_eq!(size, mem::size_of::<T>());
131 ptr as _
132 }
133}
134
135#[unstable(feature = "sgx_platform", issue = "56975")]
136unsafe impl<T: UserSafeSized> UserSafe for [T] {
137 fn align_of() -> usize {
138 mem::align_of::<T>()
139 }
140
29967ef6
XL
141 /// # Safety
142 /// Behavior is undefined if any of these conditions are violated:
143 /// * `ptr` must be [valid] for writes of `size` many bytes, and it must be
144 /// properly aligned.
145 ///
146 /// [valid]: core::ptr#safety
147 /// # Panics
148 ///
149 /// This function panics if:
150 ///
151 /// * the element size is not a factor of the size
0731742a
XL
152 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
153 let elem_size = mem::size_of::<T>();
154 assert_eq!(size % elem_size, 0);
155 let len = size / elem_size;
29967ef6
XL
156 // SAFETY: The caller must uphold the safety contract for `from_raw_sized_unchecked`
157 unsafe { slice::from_raw_parts_mut(ptr as _, len) }
0731742a
XL
158 }
159}
160
161/// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
162/// to `&T` in enclave memory. Access to the memory is only allowed by copying
163/// to avoid TOCTTOU issues. After copying, code should make sure to completely
164/// check the value before use.
165///
166/// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
167/// regular mutable references, these are not exclusive. Userspace may always
168/// write to the backing memory at any time, so it can't be assumed that there
74b04a01 169/// the pointed-to memory is uniquely borrowed. The two different reference types
0731742a
XL
170/// are used solely to indicate intent: a mutable reference is for writing to
171/// user memory, an immutable reference for reading from user memory.
172#[unstable(feature = "sgx_platform", issue = "56975")]
173pub struct UserRef<T: ?Sized>(UnsafeCell<T>);
174/// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
175/// enclave memory. Access to the memory is only allowed by copying to avoid
176/// TOCTTOU issues. The user memory will be freed when the value is dropped.
177/// After copying, code should make sure to completely check the value before
178/// use.
179#[unstable(feature = "sgx_platform", issue = "56975")]
180pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>);
181
182trait NewUserRef<T: ?Sized> {
183 unsafe fn new_userref(v: T) -> Self;
184}
185
186impl<T: ?Sized> NewUserRef<*mut T> for NonNull<UserRef<T>> {
187 unsafe fn new_userref(v: *mut T) -> Self {
29967ef6
XL
188 // SAFETY: The caller has guaranteed the pointer is valid
189 unsafe { NonNull::new_unchecked(v as _) }
0731742a
XL
190 }
191}
192
193impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
194 unsafe fn new_userref(v: NonNull<T>) -> Self {
29967ef6
XL
195 // SAFETY: The caller has guaranteed the pointer is valid
196 unsafe { NonNull::new_userref(v.as_ptr()) }
0731742a
XL
197 }
198}
199
200#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
201impl<T: ?Sized> User<T>
202where
203 T: UserSafe,
204{
0731742a
XL
205 // This function returns memory that is practically uninitialized, but is
206 // not considered "unspecified" or "undefined" for purposes of an
207 // optimizing compiler. This is achieved by returning a pointer from
208 // from outside as obtained by `super::alloc`.
209 fn new_uninit_bytes(size: usize) -> Self {
210 unsafe {
532ac7d7
XL
211 // Mustn't call alloc with size 0.
212 let ptr = if size > 0 {
213 rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
214 } else {
215 T::align_of() as _ // dangling pointer ok for size 0
216 };
217 if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) {
218 User(NonNull::new_userref(v))
219 } else {
220 rtabort!("Got invalid pointer from alloc() usercall")
221 }
0731742a
XL
222 }
223 }
224
9fa01778 225 /// Copies `val` into freshly allocated space in user memory.
0731742a
XL
226 pub fn new_from_enclave(val: &T) -> Self {
227 unsafe {
228 let ret = Self::new_uninit_bytes(mem::size_of_val(val));
229 ptr::copy(
230 val as *const T as *const u8,
231 ret.0.as_ptr() as *mut u8,
60c5eb7d 232 mem::size_of_val(val),
0731742a
XL
233 );
234 ret
235 }
236 }
237
9fa01778 238 /// Creates an owned `User<T>` from a raw pointer.
0731742a
XL
239 ///
240 /// # Safety
241 /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
242 /// usercall and the alignment of `T`, and is uniquely owned.
243 ///
244 /// # Panics
245 /// This function panics if:
246 ///
247 /// * The pointer is not aligned
248 /// * The pointer is null
249 /// * The pointed-to range is not in user memory
250 pub unsafe fn from_raw(ptr: *mut T) -> Self {
29967ef6
XL
251 // SAFETY: the caller must uphold the safety contract for `from_raw`.
252 unsafe { T::check_ptr(ptr) };
253 User(unsafe { NonNull::new_userref(ptr) })
0731742a
XL
254 }
255
9fa01778 256 /// Converts this value into a raw pointer. The value will no longer be
0731742a
XL
257 /// automatically freed.
258 pub fn into_raw(self) -> *mut T {
259 let ret = self.0;
260 mem::forget(self);
261 ret.as_ptr() as _
262 }
263}
264
265#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
266impl<T> User<T>
267where
268 T: UserSafe,
269{
0731742a
XL
270 /// Allocate space for `T` in user memory.
271 pub fn uninitialized() -> Self {
272 Self::new_uninit_bytes(mem::size_of::<T>())
273 }
274}
275
276#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
277impl<T> User<[T]>
278where
279 [T]: UserSafe,
280{
0731742a
XL
281 /// Allocate space for a `[T]` of `n` elements in user memory.
282 pub fn uninitialized(n: usize) -> Self {
283 Self::new_uninit_bytes(n * mem::size_of::<T>())
284 }
285
9fa01778 286 /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
287 ///
288 /// # Safety
289 /// The caller must ensure `ptr` points to `len` elements of `T`, is
290 /// freeable with the `free` usercall and the alignment of `T`, and is
291 /// uniquely owned.
292 ///
293 /// # Panics
294 /// This function panics if:
295 ///
296 /// * The pointer is not aligned
297 /// * The pointer is null
48663c56 298 /// * The pointed-to range does not fit in the address space
0731742a
XL
299 /// * The pointed-to range is not in user memory
300 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
29967ef6
XL
301 User(unsafe {
302 NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()))
303 })
0731742a
XL
304 }
305}
306
307#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
308impl<T: ?Sized> UserRef<T>
309where
310 T: UserSafe,
311{
9fa01778 312 /// Creates a `&UserRef<[T]>` from a raw pointer.
0731742a
XL
313 ///
314 /// # Safety
315 /// The caller must ensure `ptr` points to `T`.
316 ///
317 /// # Panics
318 /// This function panics if:
319 ///
320 /// * The pointer is not aligned
321 /// * The pointer is null
322 /// * The pointed-to range is not in user memory
323 pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
29967ef6
XL
324 // SAFETY: The caller must uphold the safety contract for `from_ptr`.
325 unsafe { T::check_ptr(ptr) };
326 unsafe { &*(ptr as *const Self) }
0731742a
XL
327 }
328
9fa01778 329 /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct
0731742a
XL
330 /// documentation for the nuances regarding a `&mut UserRef<T>`.
331 ///
332 /// # Safety
333 /// The caller must ensure `ptr` points to `T`.
334 ///
335 /// # Panics
336 /// This function panics if:
337 ///
338 /// * The pointer is not aligned
339 /// * The pointer is null
340 /// * The pointed-to range is not in user memory
341 pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
29967ef6
XL
342 // SAFETY: The caller must uphold the safety contract for `from_mut_ptr`.
343 unsafe { T::check_ptr(ptr) };
344 unsafe { &mut *(ptr as *mut Self) }
0731742a
XL
345 }
346
9fa01778 347 /// Copies `val` into user memory.
0731742a
XL
348 ///
349 /// # Panics
350 /// This function panics if the destination doesn't have the same size as
351 /// the source. This can happen for dynamically-sized types such as slices.
352 pub fn copy_from_enclave(&mut self, val: &T) {
353 unsafe {
60c5eb7d 354 assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get()));
0731742a
XL
355 ptr::copy(
356 val as *const T as *const u8,
357 self.0.get() as *mut T as *mut u8,
60c5eb7d 358 mem::size_of_val(val),
0731742a
XL
359 );
360 }
361 }
362
9fa01778 363 /// Copies the value from user memory and place it into `dest`.
0731742a
XL
364 ///
365 /// # Panics
366 /// This function panics if the destination doesn't have the same size as
367 /// the source. This can happen for dynamically-sized types such as slices.
368 pub fn copy_to_enclave(&self, dest: &mut T) {
369 unsafe {
60c5eb7d 370 assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get()));
0731742a
XL
371 ptr::copy(
372 self.0.get() as *const T as *const u8,
373 dest as *mut T as *mut u8,
60c5eb7d 374 mem::size_of_val(dest),
0731742a
XL
375 );
376 }
377 }
378
379 /// Obtain a raw pointer from this reference.
380 pub fn as_raw_ptr(&self) -> *const T {
381 self as *const _ as _
382 }
383
384 /// Obtain a raw pointer from this reference.
385 pub fn as_raw_mut_ptr(&mut self) -> *mut T {
386 self as *mut _ as _
387 }
388}
389
390#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
391impl<T> UserRef<T>
392where
393 T: UserSafe,
394{
9fa01778 395 /// Copies the value from user memory into enclave memory.
0731742a
XL
396 pub fn to_enclave(&self) -> T {
397 unsafe { ptr::read(self.0.get()) }
398 }
399}
400
401#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
402impl<T> UserRef<[T]>
403where
404 [T]: UserSafe,
405{
9fa01778 406 /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
407 ///
408 /// # Safety
409 /// The caller must ensure `ptr` points to `n` elements of `T`.
410 ///
411 /// # Panics
412 /// This function panics if:
413 ///
414 /// * The pointer is not aligned
415 /// * The pointer is null
48663c56 416 /// * The pointed-to range does not fit in the address space
0731742a
XL
417 /// * The pointed-to range is not in user memory
418 pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
29967ef6
XL
419 // SAFETY: The caller must uphold the safety contract for `from_raw_parts`.
420 unsafe {
421 &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
422 }
0731742a
XL
423 }
424
9fa01778 425 /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
426 /// See the struct documentation for the nuances regarding a
427 /// `&mut UserRef<T>`.
428 ///
429 /// # Safety
430 /// The caller must ensure `ptr` points to `n` elements of `T`.
431 ///
432 /// # Panics
433 /// This function panics if:
434 ///
435 /// * The pointer is not aligned
436 /// * The pointer is null
48663c56 437 /// * The pointed-to range does not fit in the address space
0731742a
XL
438 /// * The pointed-to range is not in user memory
439 pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
29967ef6
XL
440 // SAFETY: The caller must uphold the safety contract for `from_raw_parts_mut`.
441 unsafe {
442 &mut *(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
443 }
0731742a
XL
444 }
445
446 /// Obtain a raw pointer to the first element of this user slice.
447 pub fn as_ptr(&self) -> *const T {
448 self.0.get() as _
449 }
450
451 /// Obtain a raw pointer to the first element of this user slice.
452 pub fn as_mut_ptr(&mut self) -> *mut T {
453 self.0.get() as _
454 }
455
456 /// Obtain the number of elements in this user slice.
457 pub fn len(&self) -> usize {
458 unsafe { (*self.0.get()).len() }
459 }
460
9fa01778 461 /// Copies the value from user memory and place it into `dest`. Afterwards,
0731742a
XL
462 /// `dest` will contain exactly `self.len()` elements.
463 ///
464 /// # Panics
465 /// This function panics if the destination doesn't have the same size as
466 /// the source. This can happen for dynamically-sized types such as slices.
467 pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
29967ef6
XL
468 if let Some(missing) = self.len().checked_sub(dest.capacity()) {
469 dest.reserve(missing)
0731742a 470 }
29967ef6
XL
471 // SAFETY: We reserve enough space above.
472 unsafe { dest.set_len(self.len()) };
473 self.copy_to_enclave(&mut dest[..]);
0731742a
XL
474 }
475
9fa01778 476 /// Copies the value from user memory into a vector in enclave memory.
0731742a
XL
477 pub fn to_enclave(&self) -> Vec<T> {
478 let mut ret = Vec::with_capacity(self.len());
479 self.copy_to_enclave_vec(&mut ret);
480 ret
481 }
482
483 /// Returns an iterator over the slice.
532ac7d7 484 pub fn iter(&self) -> Iter<'_, T>
60c5eb7d
XL
485 where
486 T: UserSafe, // FIXME: should be implied by [T]: UserSafe?
0731742a 487 {
60c5eb7d 488 unsafe { Iter((&*self.as_raw_ptr()).iter()) }
0731742a
XL
489 }
490
491 /// Returns an iterator that allows modifying each value.
532ac7d7 492 pub fn iter_mut(&mut self) -> IterMut<'_, T>
60c5eb7d
XL
493 where
494 T: UserSafe, // FIXME: should be implied by [T]: UserSafe?
0731742a 495 {
60c5eb7d 496 unsafe { IterMut((&mut *self.as_raw_mut_ptr()).iter_mut()) }
0731742a
XL
497 }
498}
499
500/// Immutable user slice iterator
501///
502/// This struct is created by the `iter` method on `UserRef<[T]>`.
503#[unstable(feature = "sgx_platform", issue = "56975")]
504pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
505
506#[unstable(feature = "sgx_platform", issue = "56975")]
507impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
508 type Item = &'a UserRef<T>;
509
510 #[inline]
511 fn next(&mut self) -> Option<Self::Item> {
60c5eb7d 512 unsafe { self.0.next().map(|e| UserRef::from_ptr(e)) }
0731742a
XL
513 }
514}
515
516/// Mutable user slice iterator
517///
518/// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
519#[unstable(feature = "sgx_platform", issue = "56975")]
520pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
521
522#[unstable(feature = "sgx_platform", issue = "56975")]
523impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
524 type Item = &'a mut UserRef<T>;
525
526 #[inline]
527 fn next(&mut self) -> Option<Self::Item> {
60c5eb7d 528 unsafe { self.0.next().map(|e| UserRef::from_mut_ptr(e)) }
0731742a
XL
529 }
530}
531
532#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
533impl<T: ?Sized> Deref for User<T>
534where
535 T: UserSafe,
536{
0731742a
XL
537 type Target = UserRef<T>;
538
539 fn deref(&self) -> &Self::Target {
540 unsafe { &*self.0.as_ptr() }
541 }
542}
543
544#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
545impl<T: ?Sized> DerefMut for User<T>
546where
547 T: UserSafe,
548{
0731742a 549 fn deref_mut(&mut self) -> &mut Self::Target {
60c5eb7d 550 unsafe { &mut *self.0.as_ptr() }
0731742a
XL
551 }
552}
553
554#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
555impl<T: ?Sized> Drop for User<T>
556where
557 T: UserSafe,
558{
0731742a
XL
559 fn drop(&mut self) {
560 unsafe {
561 let ptr = (*self.0.as_ptr()).0.get();
60c5eb7d 562 super::free(ptr as _, mem::size_of_val(&mut *ptr), T::align_of());
0731742a
XL
563 }
564 }
565}
566
567#[unstable(feature = "sgx_platform", issue = "56975")]
568impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
569
570#[unstable(feature = "sgx_platform", issue = "56975")]
416331ca
XL
571impl<T, I> Index<I> for UserRef<[T]>
572where
573 [T]: UserSafe,
ee023bcb
FG
574 I: SliceIndex<[T]>,
575 I::Output: UserSafe,
416331ca 576{
0731742a
XL
577 type Output = UserRef<I::Output>;
578
579 #[inline]
580 fn index(&self, index: I) -> &UserRef<I::Output> {
581 unsafe {
48663c56
XL
582 if let Some(slice) = index.get(&*self.as_raw_ptr()) {
583 UserRef::from_ptr(slice)
584 } else {
585 rtabort!("index out of range for user slice");
586 }
0731742a
XL
587 }
588 }
589}
590
591#[unstable(feature = "sgx_platform", issue = "56975")]
416331ca
XL
592impl<T, I> IndexMut<I> for UserRef<[T]>
593where
594 [T]: UserSafe,
ee023bcb
FG
595 I: SliceIndex<[T]>,
596 I::Output: UserSafe,
416331ca 597{
0731742a
XL
598 #[inline]
599 fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
600 unsafe {
60c5eb7d 601 if let Some(slice) = index.get_mut(&mut *self.as_raw_mut_ptr()) {
48663c56
XL
602 UserRef::from_mut_ptr(slice)
603 } else {
604 rtabort!("index out of range for user slice");
605 }
0731742a
XL
606 }
607 }
608}
609
610#[unstable(feature = "sgx_platform", issue = "56975")]
611impl UserRef<super::raw::ByteBuffer> {
9fa01778 612 /// Copies the user memory range pointed to by the user `ByteBuffer` to
0731742a
XL
613 /// enclave memory.
614 ///
615 /// # Panics
48663c56 616 /// This function panics if, in the user `ByteBuffer`:
0731742a 617 ///
48663c56
XL
618 /// * The pointer is null
619 /// * The pointed-to range does not fit in the address space
620 /// * The pointed-to range is not in user memory
0731742a
XL
621 pub fn copy_user_buffer(&self) -> Vec<u8> {
622 unsafe {
623 let buf = self.to_enclave();
9fa01778
XL
624 if buf.len > 0 {
625 User::from_raw_parts(buf.data as _, buf.len).to_enclave()
626 } else {
627 // Mustn't look at `data` or call `free` if `len` is `0`.
628 Vec::with_capacity(0)
629 }
0731742a
XL
630 }
631 }
632}