]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/sgx/abi/usercalls/alloc.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libstd / 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);
0731742a
XL
92 let ret = Self::from_raw_sized_unchecked(ptr, size);
93 Self::check_ptr(ret);
94 NonNull::new_unchecked(ret as _)
95 }
96
9fa01778 97 /// Checks if a pointer may point to `Self` in user memory.
0731742a
XL
98 ///
99 /// # Safety
9fa01778 100 ///
0731742a
XL
101 /// The caller must ensure the memory range points to the correct type and
102 /// length (if this is a slice).
103 ///
104 /// # Panics
9fa01778 105 ///
0731742a
XL
106 /// This function panics if:
107 ///
9fa01778
XL
108 /// * the pointer is not aligned.
109 /// * the pointer is null.
110 /// * the pointed-to range is not in user memory.
0731742a 111 unsafe fn check_ptr(ptr: *const Self) {
60c5eb7d 112 let is_aligned = |p| -> bool { 0 == (p as usize) & (Self::align_of() - 1) };
0731742a
XL
113
114 assert!(is_aligned(ptr as *const u8));
115 assert!(is_user_range(ptr as _, mem::size_of_val(&*ptr)));
116 assert!(!ptr.is_null());
117 }
118}
119
120#[unstable(feature = "sgx_platform", issue = "56975")]
121unsafe impl<T: UserSafeSized> UserSafe for T {
122 fn align_of() -> usize {
123 mem::align_of::<T>()
124 }
125
126 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
127 assert_eq!(size, mem::size_of::<T>());
128 ptr as _
129 }
130}
131
132#[unstable(feature = "sgx_platform", issue = "56975")]
133unsafe impl<T: UserSafeSized> UserSafe for [T] {
134 fn align_of() -> usize {
135 mem::align_of::<T>()
136 }
137
138 unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self {
139 let elem_size = mem::size_of::<T>();
140 assert_eq!(size % elem_size, 0);
141 let len = size / elem_size;
142 slice::from_raw_parts_mut(ptr as _, len)
143 }
144}
145
146/// A reference to some type in userspace memory. `&UserRef<T>` is equivalent
147/// to `&T` in enclave memory. Access to the memory is only allowed by copying
148/// to avoid TOCTTOU issues. After copying, code should make sure to completely
149/// check the value before use.
150///
151/// It is also possible to obtain a mutable reference `&mut UserRef<T>`. Unlike
152/// regular mutable references, these are not exclusive. Userspace may always
153/// write to the backing memory at any time, so it can't be assumed that there
154/// the pointed-to memory is uniquely borrowed. The two different refence types
155/// are used solely to indicate intent: a mutable reference is for writing to
156/// user memory, an immutable reference for reading from user memory.
157#[unstable(feature = "sgx_platform", issue = "56975")]
158pub struct UserRef<T: ?Sized>(UnsafeCell<T>);
159/// An owned type in userspace memory. `User<T>` is equivalent to `Box<T>` in
160/// enclave memory. Access to the memory is only allowed by copying to avoid
161/// TOCTTOU issues. The user memory will be freed when the value is dropped.
162/// After copying, code should make sure to completely check the value before
163/// use.
164#[unstable(feature = "sgx_platform", issue = "56975")]
165pub struct User<T: UserSafe + ?Sized>(NonNull<UserRef<T>>);
166
167trait NewUserRef<T: ?Sized> {
168 unsafe fn new_userref(v: T) -> Self;
169}
170
171impl<T: ?Sized> NewUserRef<*mut T> for NonNull<UserRef<T>> {
172 unsafe fn new_userref(v: *mut T) -> Self {
173 NonNull::new_unchecked(v as _)
174 }
175}
176
177impl<T: ?Sized> NewUserRef<NonNull<T>> for NonNull<UserRef<T>> {
178 unsafe fn new_userref(v: NonNull<T>) -> Self {
179 NonNull::new_userref(v.as_ptr())
180 }
181}
182
183#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
184impl<T: ?Sized> User<T>
185where
186 T: UserSafe,
187{
0731742a
XL
188 // This function returns memory that is practically uninitialized, but is
189 // not considered "unspecified" or "undefined" for purposes of an
190 // optimizing compiler. This is achieved by returning a pointer from
191 // from outside as obtained by `super::alloc`.
192 fn new_uninit_bytes(size: usize) -> Self {
193 unsafe {
532ac7d7
XL
194 // Mustn't call alloc with size 0.
195 let ptr = if size > 0 {
196 rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
197 } else {
198 T::align_of() as _ // dangling pointer ok for size 0
199 };
200 if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) {
201 User(NonNull::new_userref(v))
202 } else {
203 rtabort!("Got invalid pointer from alloc() usercall")
204 }
0731742a
XL
205 }
206 }
207
9fa01778 208 /// Copies `val` into freshly allocated space in user memory.
0731742a
XL
209 pub fn new_from_enclave(val: &T) -> Self {
210 unsafe {
211 let ret = Self::new_uninit_bytes(mem::size_of_val(val));
212 ptr::copy(
213 val as *const T as *const u8,
214 ret.0.as_ptr() as *mut u8,
60c5eb7d 215 mem::size_of_val(val),
0731742a
XL
216 );
217 ret
218 }
219 }
220
9fa01778 221 /// Creates an owned `User<T>` from a raw pointer.
0731742a
XL
222 ///
223 /// # Safety
224 /// The caller must ensure `ptr` points to `T`, is freeable with the `free`
225 /// usercall and the alignment of `T`, and is uniquely owned.
226 ///
227 /// # Panics
228 /// This function panics if:
229 ///
230 /// * The pointer is not aligned
231 /// * The pointer is null
232 /// * The pointed-to range is not in user memory
233 pub unsafe fn from_raw(ptr: *mut T) -> Self {
234 T::check_ptr(ptr);
235 User(NonNull::new_userref(ptr))
236 }
237
9fa01778 238 /// Converts this value into a raw pointer. The value will no longer be
0731742a
XL
239 /// automatically freed.
240 pub fn into_raw(self) -> *mut T {
241 let ret = self.0;
242 mem::forget(self);
243 ret.as_ptr() as _
244 }
245}
246
247#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
248impl<T> User<T>
249where
250 T: UserSafe,
251{
0731742a
XL
252 /// Allocate space for `T` in user memory.
253 pub fn uninitialized() -> Self {
254 Self::new_uninit_bytes(mem::size_of::<T>())
255 }
256}
257
258#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
259impl<T> User<[T]>
260where
261 [T]: UserSafe,
262{
0731742a
XL
263 /// Allocate space for a `[T]` of `n` elements in user memory.
264 pub fn uninitialized(n: usize) -> Self {
265 Self::new_uninit_bytes(n * mem::size_of::<T>())
266 }
267
9fa01778 268 /// Creates an owned `User<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
269 ///
270 /// # Safety
271 /// The caller must ensure `ptr` points to `len` elements of `T`, is
272 /// freeable with the `free` usercall and the alignment of `T`, and is
273 /// uniquely owned.
274 ///
275 /// # Panics
276 /// This function panics if:
277 ///
278 /// * The pointer is not aligned
279 /// * The pointer is null
48663c56 280 /// * The pointed-to range does not fit in the address space
0731742a
XL
281 /// * The pointed-to range is not in user memory
282 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
283 User(NonNull::new_userref(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>())))
284 }
285}
286
287#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
288impl<T: ?Sized> UserRef<T>
289where
290 T: UserSafe,
291{
9fa01778 292 /// Creates a `&UserRef<[T]>` from a raw pointer.
0731742a
XL
293 ///
294 /// # Safety
295 /// The caller must ensure `ptr` points to `T`.
296 ///
297 /// # Panics
298 /// This function panics if:
299 ///
300 /// * The pointer is not aligned
301 /// * The pointer is null
302 /// * The pointed-to range is not in user memory
303 pub unsafe fn from_ptr<'a>(ptr: *const T) -> &'a Self {
304 T::check_ptr(ptr);
305 &*(ptr as *const Self)
306 }
307
9fa01778 308 /// Creates a `&mut UserRef<[T]>` from a raw pointer. See the struct
0731742a
XL
309 /// documentation for the nuances regarding a `&mut UserRef<T>`.
310 ///
311 /// # Safety
312 /// The caller must ensure `ptr` points to `T`.
313 ///
314 /// # Panics
315 /// This function panics if:
316 ///
317 /// * The pointer is not aligned
318 /// * The pointer is null
319 /// * The pointed-to range is not in user memory
320 pub unsafe fn from_mut_ptr<'a>(ptr: *mut T) -> &'a mut Self {
321 T::check_ptr(ptr);
60c5eb7d 322 &mut *(ptr as *mut Self)
0731742a
XL
323 }
324
9fa01778 325 /// Copies `val` into user memory.
0731742a
XL
326 ///
327 /// # Panics
328 /// This function panics if the destination doesn't have the same size as
329 /// the source. This can happen for dynamically-sized types such as slices.
330 pub fn copy_from_enclave(&mut self, val: &T) {
331 unsafe {
60c5eb7d 332 assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get()));
0731742a
XL
333 ptr::copy(
334 val as *const T as *const u8,
335 self.0.get() as *mut T as *mut u8,
60c5eb7d 336 mem::size_of_val(val),
0731742a
XL
337 );
338 }
339 }
340
9fa01778 341 /// Copies the value from user memory and place it into `dest`.
0731742a
XL
342 ///
343 /// # Panics
344 /// This function panics if the destination doesn't have the same size as
345 /// the source. This can happen for dynamically-sized types such as slices.
346 pub fn copy_to_enclave(&self, dest: &mut T) {
347 unsafe {
60c5eb7d 348 assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get()));
0731742a
XL
349 ptr::copy(
350 self.0.get() as *const T as *const u8,
351 dest as *mut T as *mut u8,
60c5eb7d 352 mem::size_of_val(dest),
0731742a
XL
353 );
354 }
355 }
356
357 /// Obtain a raw pointer from this reference.
358 pub fn as_raw_ptr(&self) -> *const T {
359 self as *const _ as _
360 }
361
362 /// Obtain a raw pointer from this reference.
363 pub fn as_raw_mut_ptr(&mut self) -> *mut T {
364 self as *mut _ as _
365 }
366}
367
368#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
369impl<T> UserRef<T>
370where
371 T: UserSafe,
372{
9fa01778 373 /// Copies the value from user memory into enclave memory.
0731742a
XL
374 pub fn to_enclave(&self) -> T {
375 unsafe { ptr::read(self.0.get()) }
376 }
377}
378
379#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
380impl<T> UserRef<[T]>
381where
382 [T]: UserSafe,
383{
9fa01778 384 /// Creates a `&UserRef<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
385 ///
386 /// # Safety
387 /// The caller must ensure `ptr` points to `n` elements of `T`.
388 ///
389 /// # Panics
390 /// This function panics if:
391 ///
392 /// * The pointer is not aligned
393 /// * The pointer is null
48663c56 394 /// * The pointed-to range does not fit in the address space
0731742a
XL
395 /// * The pointed-to range is not in user memory
396 pub unsafe fn from_raw_parts<'a>(ptr: *const T, len: usize) -> &'a Self {
397 &*(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *const Self)
398 }
399
9fa01778 400 /// Creates a `&mut UserRef<[T]>` from a raw thin pointer and a slice length.
0731742a
XL
401 /// See the struct documentation for the nuances regarding a
402 /// `&mut UserRef<T>`.
403 ///
404 /// # Safety
405 /// The caller must ensure `ptr` points to `n` elements of `T`.
406 ///
407 /// # Panics
408 /// This function panics if:
409 ///
410 /// * The pointer is not aligned
411 /// * The pointer is null
48663c56 412 /// * The pointed-to range does not fit in the address space
0731742a
XL
413 /// * The pointed-to range is not in user memory
414 pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut T, len: usize) -> &'a mut Self {
60c5eb7d 415 &mut *(<[T]>::from_raw_sized(ptr as _, len * mem::size_of::<T>()).as_ptr() as *mut Self)
0731742a
XL
416 }
417
418 /// Obtain a raw pointer to the first element of this user slice.
419 pub fn as_ptr(&self) -> *const T {
420 self.0.get() as _
421 }
422
423 /// Obtain a raw pointer to the first element of this user slice.
424 pub fn as_mut_ptr(&mut self) -> *mut T {
425 self.0.get() as _
426 }
427
428 /// Obtain the number of elements in this user slice.
429 pub fn len(&self) -> usize {
430 unsafe { (*self.0.get()).len() }
431 }
432
9fa01778 433 /// Copies the value from user memory and place it into `dest`. Afterwards,
0731742a
XL
434 /// `dest` will contain exactly `self.len()` elements.
435 ///
436 /// # Panics
437 /// This function panics if the destination doesn't have the same size as
438 /// the source. This can happen for dynamically-sized types such as slices.
439 pub fn copy_to_enclave_vec(&self, dest: &mut Vec<T>) {
440 unsafe {
441 if let Some(missing) = self.len().checked_sub(dest.capacity()) {
442 dest.reserve(missing)
443 }
444 dest.set_len(self.len());
445 self.copy_to_enclave(&mut dest[..]);
446 }
447 }
448
9fa01778 449 /// Copies the value from user memory into a vector in enclave memory.
0731742a
XL
450 pub fn to_enclave(&self) -> Vec<T> {
451 let mut ret = Vec::with_capacity(self.len());
452 self.copy_to_enclave_vec(&mut ret);
453 ret
454 }
455
456 /// Returns an iterator over the slice.
532ac7d7 457 pub fn iter(&self) -> Iter<'_, T>
60c5eb7d
XL
458 where
459 T: UserSafe, // FIXME: should be implied by [T]: UserSafe?
0731742a 460 {
60c5eb7d 461 unsafe { Iter((&*self.as_raw_ptr()).iter()) }
0731742a
XL
462 }
463
464 /// Returns an iterator that allows modifying each value.
532ac7d7 465 pub fn iter_mut(&mut self) -> IterMut<'_, T>
60c5eb7d
XL
466 where
467 T: UserSafe, // FIXME: should be implied by [T]: UserSafe?
0731742a 468 {
60c5eb7d 469 unsafe { IterMut((&mut *self.as_raw_mut_ptr()).iter_mut()) }
0731742a
XL
470 }
471}
472
473/// Immutable user slice iterator
474///
475/// This struct is created by the `iter` method on `UserRef<[T]>`.
476#[unstable(feature = "sgx_platform", issue = "56975")]
477pub struct Iter<'a, T: 'a + UserSafe>(slice::Iter<'a, T>);
478
479#[unstable(feature = "sgx_platform", issue = "56975")]
480impl<'a, T: UserSafe> Iterator for Iter<'a, T> {
481 type Item = &'a UserRef<T>;
482
483 #[inline]
484 fn next(&mut self) -> Option<Self::Item> {
60c5eb7d 485 unsafe { self.0.next().map(|e| UserRef::from_ptr(e)) }
0731742a
XL
486 }
487}
488
489/// Mutable user slice iterator
490///
491/// This struct is created by the `iter_mut` method on `UserRef<[T]>`.
492#[unstable(feature = "sgx_platform", issue = "56975")]
493pub struct IterMut<'a, T: 'a + UserSafe>(slice::IterMut<'a, T>);
494
495#[unstable(feature = "sgx_platform", issue = "56975")]
496impl<'a, T: UserSafe> Iterator for IterMut<'a, T> {
497 type Item = &'a mut UserRef<T>;
498
499 #[inline]
500 fn next(&mut self) -> Option<Self::Item> {
60c5eb7d 501 unsafe { self.0.next().map(|e| UserRef::from_mut_ptr(e)) }
0731742a
XL
502 }
503}
504
505#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
506impl<T: ?Sized> Deref for User<T>
507where
508 T: UserSafe,
509{
0731742a
XL
510 type Target = UserRef<T>;
511
512 fn deref(&self) -> &Self::Target {
513 unsafe { &*self.0.as_ptr() }
514 }
515}
516
517#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
518impl<T: ?Sized> DerefMut for User<T>
519where
520 T: UserSafe,
521{
0731742a 522 fn deref_mut(&mut self) -> &mut Self::Target {
60c5eb7d 523 unsafe { &mut *self.0.as_ptr() }
0731742a
XL
524 }
525}
526
527#[unstable(feature = "sgx_platform", issue = "56975")]
60c5eb7d
XL
528impl<T: ?Sized> Drop for User<T>
529where
530 T: UserSafe,
531{
0731742a
XL
532 fn drop(&mut self) {
533 unsafe {
534 let ptr = (*self.0.as_ptr()).0.get();
60c5eb7d 535 super::free(ptr as _, mem::size_of_val(&mut *ptr), T::align_of());
0731742a
XL
536 }
537 }
538}
539
540#[unstable(feature = "sgx_platform", issue = "56975")]
541impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
542
543#[unstable(feature = "sgx_platform", issue = "56975")]
416331ca
XL
544impl<T, I> Index<I> for UserRef<[T]>
545where
546 [T]: UserSafe,
547 I: SliceIndex<[T], Output: UserSafe>,
548{
0731742a
XL
549 type Output = UserRef<I::Output>;
550
551 #[inline]
552 fn index(&self, index: I) -> &UserRef<I::Output> {
553 unsafe {
48663c56
XL
554 if let Some(slice) = index.get(&*self.as_raw_ptr()) {
555 UserRef::from_ptr(slice)
556 } else {
557 rtabort!("index out of range for user slice");
558 }
0731742a
XL
559 }
560 }
561}
562
563#[unstable(feature = "sgx_platform", issue = "56975")]
416331ca
XL
564impl<T, I> IndexMut<I> for UserRef<[T]>
565where
566 [T]: UserSafe,
567 I: SliceIndex<[T], Output: UserSafe>,
568{
0731742a
XL
569 #[inline]
570 fn index_mut(&mut self, index: I) -> &mut UserRef<I::Output> {
571 unsafe {
60c5eb7d 572 if let Some(slice) = index.get_mut(&mut *self.as_raw_mut_ptr()) {
48663c56
XL
573 UserRef::from_mut_ptr(slice)
574 } else {
575 rtabort!("index out of range for user slice");
576 }
0731742a
XL
577 }
578 }
579}
580
581#[unstable(feature = "sgx_platform", issue = "56975")]
582impl UserRef<super::raw::ByteBuffer> {
9fa01778 583 /// Copies the user memory range pointed to by the user `ByteBuffer` to
0731742a
XL
584 /// enclave memory.
585 ///
586 /// # Panics
48663c56 587 /// This function panics if, in the user `ByteBuffer`:
0731742a 588 ///
48663c56
XL
589 /// * The pointer is null
590 /// * The pointed-to range does not fit in the address space
591 /// * The pointed-to range is not in user memory
0731742a
XL
592 pub fn copy_user_buffer(&self) -> Vec<u8> {
593 unsafe {
594 let buf = self.to_enclave();
9fa01778
XL
595 if buf.len > 0 {
596 User::from_raw_parts(buf.data as _, buf.len).to_enclave()
597 } else {
598 // Mustn't look at `data` or call `free` if `len` is `0`.
599 Vec::with_capacity(0)
600 }
0731742a
XL
601 }
602 }
603}