1#[cfg(not(feature = "std"))]
2use alloc::{Layout, alloc, dealloc};
3
4#[cfg(feature = "std")]
5use std::vec::Vec;
6
7use super::{Error, SecureArray};
8use core::{
9 marker::PhantomData,
10 mem,
11 ops::{Bound, RangeBounds},
12 ptr::{self, NonNull},
13};
14use zeroize::{DefaultIsZeroes, Zeroize};
15
16#[cfg(feature = "std")]
17use super::page_size;
18#[cfg(feature = "std")]
19use memsec::Prot;
20
21pub type SecureBytes = SecureVec<u8>;
22
23pub struct SecureVec<T>
73where
74 T: Zeroize,
75{
76 ptr: NonNull<T>,
77 pub(crate) len: usize,
78 pub(crate) capacity: usize,
79 _marker: PhantomData<T>,
80}
81
82unsafe impl<T: Zeroize + Send> Send for SecureVec<T> {}
83unsafe impl<T: Zeroize + Send + Sync> Sync for SecureVec<T> {}
84
85impl<T: Zeroize> SecureVec<T> {
86 pub fn new() -> Result<Self, Error> {
87 let capacity = 1;
89 let size = capacity * mem::size_of::<T>();
90
91 #[cfg(feature = "std")]
92 let ptr = unsafe {
93 let aligned_size = (size + page_size() - 1) & !(page_size() - 1);
94 let allocated_ptr = memsec::malloc_sized(aligned_size);
95 let ptr = allocated_ptr.ok_or(Error::AllocationFailed)?;
96 ptr.as_ptr() as *mut T
97 };
98
99 #[cfg(not(feature = "std"))]
100 let ptr = {
101 let layout = Layout::from_size_align(size, mem::align_of::<T>())
102 .map_err(|_| Error::AllocationFailed)?;
103 let ptr = unsafe { alloc::alloc(layout) as *mut T };
104 if ptr.is_null() {
105 return Err(Error::AllocationFailed);
106 }
107 ptr
108 };
109
110 let non_null = NonNull::new(ptr).ok_or(Error::NullAllocation)?;
111 let secure = SecureVec {
112 ptr: non_null,
113 len: 0,
114 capacity,
115 _marker: PhantomData,
116 };
117
118 let (encrypted, locked) = secure.lock_memory();
119
120 #[cfg(feature = "std")]
121 if !locked {
122 return Err(Error::LockFailed);
123 }
124
125 #[cfg(feature = "std")]
126 if !encrypted {
127 return Err(Error::CryptProtectMemoryFailed);
128 }
129
130 Ok(secure)
131 }
132
133 pub fn new_with_capacity(mut capacity: usize) -> Result<Self, Error> {
134 if capacity == 0 {
135 capacity = 1;
136 }
137
138 let size = capacity * mem::size_of::<T>();
139
140 #[cfg(feature = "std")]
141 let ptr = unsafe {
142 let aligned_size = (size + page_size() - 1) & !(page_size() - 1);
143 let allocated_ptr = memsec::malloc_sized(aligned_size);
144 let ptr = allocated_ptr.ok_or(Error::AllocationFailed)?;
145 ptr.as_ptr() as *mut T
146 };
147
148 #[cfg(not(feature = "std"))]
149 let ptr = {
150 let layout = Layout::from_size_align(size, mem::align_of::<T>())
151 .map_err(|_| Error::AllocationFailed)?;
152 let ptr = unsafe { alloc::alloc(layout) as *mut T };
153 if ptr.is_null() {
154 return Err(Error::AllocationFailed);
155 }
156 ptr
157 };
158
159 let non_null = NonNull::new(ptr).ok_or(Error::NullAllocation)?;
160
161 let secure = SecureVec {
162 ptr: non_null,
163 len: 0,
164 capacity,
165 _marker: PhantomData,
166 };
167
168 let (encrypted, locked) = secure.lock_memory();
169
170 #[cfg(feature = "std")]
171 if !locked {
172 return Err(Error::LockFailed);
173 }
174
175 #[cfg(feature = "std")]
176 if !encrypted {
177 return Err(Error::CryptProtectMemoryFailed);
178 }
179
180 Ok(secure)
181 }
182
183 #[cfg(feature = "std")]
184 pub fn from_vec(mut vec: Vec<T>) -> Result<Self, Error> {
185 if vec.capacity() == 0 {
186 vec.reserve(1);
187 }
188
189 let capacity = vec.capacity();
190 let len = vec.len();
191
192 let size = capacity * mem::size_of::<T>();
194
195 let ptr = unsafe {
196 let aligned_size = (size + page_size() - 1) & !(page_size() - 1);
197 let allocated_ptr = memsec::malloc_sized(aligned_size);
198 if allocated_ptr.is_none() {
199 vec.zeroize();
200 return Err(Error::AllocationFailed);
201 } else {
202 allocated_ptr.unwrap().as_ptr() as *mut T
203 }
204 };
205
206 unsafe {
208 core::ptr::copy_nonoverlapping(vec.as_ptr(), ptr, len);
209 }
210
211 vec.zeroize();
213 drop(vec);
214
215 let non_null = NonNull::new(ptr).ok_or(Error::NullAllocation)?;
216
217 let secure = SecureVec {
218 ptr: non_null,
219 len,
220 capacity,
221 _marker: PhantomData,
222 };
223
224 let (encrypted, locked) = secure.lock_memory();
225
226 if !locked {
227 return Err(Error::LockFailed);
228 }
229
230 if !encrypted {
231 return Err(Error::CryptProtectMemoryFailed);
232 }
233
234 Ok(secure)
235 }
236
237 pub fn from_slice_mut(slice: &mut [T]) -> Result<Self, Error>
240 where
241 T: Clone + DefaultIsZeroes,
242 {
243 let mut secure_vec = SecureVec::new_with_capacity(slice.len())?;
244 secure_vec.len = slice.len();
245 secure_vec.slice_mut_scope(|dest_slice| {
246 dest_slice.clone_from_slice(slice);
247 });
248 slice.zeroize();
249 Ok(secure_vec)
250 }
251
252 pub fn from_slice(slice: &[T]) -> Result<Self, Error>
255 where
256 T: Clone,
257 {
258 let mut secure_vec = SecureVec::new_with_capacity(slice.len())?;
259 secure_vec.len = slice.len();
260 secure_vec.slice_mut_scope(|dest_slice| {
261 dest_slice.clone_from_slice(slice);
262 });
263 Ok(secure_vec)
264 }
265
266 pub fn len(&self) -> usize {
267 self.len
268 }
269
270 pub fn as_ptr(&self) -> *const T {
271 self.ptr.as_ptr()
272 }
273
274 pub fn as_mut_ptr(&mut self) -> *mut u8 {
275 self.ptr.as_ptr() as *mut u8
276 }
277
278 #[allow(dead_code)]
279 fn allocated_byte_size(&self) -> usize {
280 let size = self.capacity * mem::size_of::<T>();
281 #[cfg(feature = "std")]
282 {
283 (size + page_size() - 1) & !(page_size() - 1)
284 }
285 #[cfg(not(feature = "std"))]
286 {
287 size }
289 }
290
291 #[cfg(all(feature = "std", windows))]
292 fn encypt_memory(&self) -> bool {
293 let ptr = self.as_ptr() as *mut u8;
294 super::crypt_protect_memory(ptr, self.allocated_byte_size())
295 }
296
297 #[cfg(all(feature = "std", windows))]
298 fn decrypt_memory(&self) -> bool {
299 let ptr = self.as_ptr() as *mut u8;
300 super::crypt_unprotect_memory(ptr, self.allocated_byte_size())
301 }
302
303 pub(crate) fn lock_memory(&self) -> (bool, bool) {
309 #[cfg(feature = "std")]
310 {
311 #[cfg(windows)]
312 {
313 let encrypt_ok = self.encypt_memory();
314 let mprotect_ok = super::mprotect(self.ptr, Prot::NoAccess);
315 (encrypt_ok, mprotect_ok)
316 }
317 #[cfg(unix)]
318 {
319 let mprotect_ok = super::mprotect(self.ptr, Prot::NoAccess);
320 (true, mprotect_ok)
321 }
322 }
323 #[cfg(not(feature = "std"))]
324 {
325 (true, true) }
327 }
328
329 pub(crate) fn unlock_memory(&self) -> (bool, bool) {
335 #[cfg(feature = "std")]
336 {
337 #[cfg(windows)]
338 {
339 let mprotect_ok = super::mprotect(self.ptr, Prot::ReadWrite);
340 if !mprotect_ok {
341 return (false, false);
342 }
343 let decrypt_ok = self.decrypt_memory();
344 (decrypt_ok, mprotect_ok)
345 }
346 #[cfg(unix)]
347 {
348 let mprotect_ok = super::mprotect(self.ptr, Prot::ReadWrite);
349 (true, mprotect_ok)
350 }
351 }
352
353 #[cfg(not(feature = "std"))]
354 {
355 (true, true) }
357 }
358
359 pub fn unlock_scope<F, R>(&self, f: F) -> R
361 where
362 F: FnOnce(&SecureVec<T>) -> R,
363 {
364 self.unlock_memory();
365 let result = f(self);
366 self.lock_memory();
367 result
368 }
369
370 pub fn slice_scope<F, R>(&self, f: F) -> R
372 where
373 F: FnOnce(&[T]) -> R,
374 {
375 unsafe {
376 self.unlock_memory();
377 let slice = core::slice::from_raw_parts(self.ptr.as_ptr(), self.len);
378 let result = f(slice);
379 self.lock_memory();
380 result
381 }
382 }
383
384 pub fn slice_mut_scope<F, R>(&mut self, f: F) -> R
386 where
387 F: FnOnce(&mut [T]) -> R,
388 {
389 unsafe {
390 self.unlock_memory();
391 let slice = core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len);
392 let result = f(slice);
393 self.lock_memory();
394 result
395 }
396 }
397
398 pub fn iter_scope<F, R>(&self, f: F) -> R
406 where
407 F: FnOnce(core::slice::Iter<T>) -> R,
408 {
409 unsafe {
410 self.unlock_memory();
411 let slice = core::slice::from_raw_parts(self.ptr.as_ptr(), self.len);
412 let iter = slice.iter();
413 let result = f(iter);
414 self.lock_memory();
415 result
416 }
417 }
418
419 pub fn iter_mut_scope<F, R>(&mut self, f: F) -> R
427 where
428 F: FnOnce(core::slice::IterMut<T>) -> R,
429 {
430 unsafe {
431 self.unlock_memory();
432 let slice = core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len);
433 let iter = slice.iter_mut();
434 let result = f(iter);
435 self.lock_memory();
436 result
437 }
438 }
439
440 pub fn erase(&mut self) {
444 unsafe {
445 self.unlock_memory();
446 let slice = core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len);
447 for elem in slice.iter_mut() {
448 elem.zeroize();
449 }
450 self.clear();
451 self.lock_memory();
452 }
453 }
454
455 pub fn clear(&mut self) {
459 self.len = 0;
460 }
461
462 pub fn push(&mut self, value: T) {
463 self.reserve(1);
468
469 self.unlock_memory();
470
471 unsafe {
472 core::ptr::write(self.ptr.as_ptr().add(self.len), value);
474
475 self.len += 1;
476 }
477
478 self.lock_memory();
479 }
480
481 pub fn reserve(&mut self, additional: usize) {
489 if self.len() + additional <= self.capacity {
490 return;
491 }
492
493 let required_capacity = self.len() + additional;
495 let new_capacity = (self.capacity.max(1) * 2).max(required_capacity);
496
497 let new_items_byte_size = new_capacity * mem::size_of::<T>();
498
499 #[cfg(feature = "std")]
501 let new_ptr = unsafe {
502 let aligned_allocation_size = (new_items_byte_size + page_size() - 1) & !(page_size() - 1);
503 memsec::malloc_sized(aligned_allocation_size)
504 .expect("Failed to allocate memory for SecureVec reserve")
505 .as_ptr() as *mut T
506 };
507
508 #[cfg(not(feature = "std"))]
509 let new_ptr = {
510 let layout = Layout::from_size_align(new_items_byte_size, mem::align_of::<T>())
511 .expect("Failed to create layout for SecureVec reserve");
512 let ptr = unsafe { alloc::alloc(layout) as *mut T };
513 if ptr.is_null() {
514 panic!("Memory allocation failed for SecureVec reserve");
515 }
516 ptr
517 };
518
519 unsafe {
521 self.unlock_memory();
522 core::ptr::copy_nonoverlapping(self.ptr.as_ptr(), new_ptr, self.len());
523
524 if self.capacity > 0 {
526 let slice = core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len);
527 for elem in slice.iter_mut() {
528 elem.zeroize();
529 }
530 }
531 #[cfg(feature = "std")]
532 memsec::free(self.ptr);
533
534 #[cfg(not(feature = "std"))]
535 {
536 let old_size = self.capacity * mem::size_of::<T>();
537 let old_layout = Layout::from_size_align_unchecked(old_size, mem::align_of::<T>());
538 dealloc(self.ptr.as_ptr() as *mut u8, old_layout);
539 }
540 }
541
542 self.ptr = NonNull::new(new_ptr).expect("New pointer was null");
544 self.capacity = new_capacity;
545 self.lock_memory();
546 }
547
548 pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
558 where
559 R: RangeBounds<usize>,
560 {
561 self.unlock_memory();
562
563 let original_len = self.len;
564
565 let (drain_start_idx, drain_end_idx) = resolve_range_indices(range, original_len);
566
567 let tail_len = original_len - drain_end_idx;
568
569 self.len = drain_start_idx;
570
571 Drain {
572 vec_ref: self,
573 drain_start_index: drain_start_idx,
574 current_drain_iter_index: drain_start_idx,
575 drain_end_index: drain_end_idx,
576 original_vec_len: original_len,
577 tail_len,
578 _marker: PhantomData,
579 }
580 }
581}
582
583impl<T: Clone + Zeroize> Clone for SecureVec<T> {
584 fn clone(&self) -> Self {
585 let mut new_vec = SecureVec::new_with_capacity(self.capacity).unwrap();
586 new_vec.len = self.len;
587
588 self.slice_scope(|src_slice| {
589 new_vec.slice_mut_scope(|dest_slice| {
590 dest_slice.clone_from_slice(src_slice);
591 });
592 });
593
594 new_vec
595 }
596}
597
598impl<const LENGTH: usize> From<SecureArray<u8, LENGTH>> for SecureVec<u8> {
599 fn from(array: SecureArray<u8, LENGTH>) -> Self {
600 let mut new_vec = SecureVec::new_with_capacity(LENGTH)
601 .expect("Failed to allocate SecureVec during conversion");
602 new_vec.len = array.len();
603
604 array.unlocked_scope(|array_slice| {
605 new_vec.slice_mut_scope(|vec_slice| {
606 vec_slice.copy_from_slice(array_slice);
607 });
608 });
609
610 new_vec
611 }
612}
613
614impl<T: Zeroize> Drop for SecureVec<T> {
615 fn drop(&mut self) {
616 self.erase();
617 self.unlock_memory();
618 unsafe {
619 #[cfg(feature = "std")]
620 memsec::free(self.ptr);
621
622 #[cfg(not(feature = "std"))]
623 {
624 let layout =
626 Layout::from_size_align_unchecked(self.allocated_byte_size(), mem::align_of::<T>());
627 dealloc(self.ptr.as_ptr() as *mut u8, layout);
628 }
629 }
630 }
631}
632
633impl<T: Zeroize> core::ops::Index<usize> for SecureVec<T> {
634 type Output = T;
635
636 fn index(&self, index: usize) -> &Self::Output {
637 assert!(index < self.len, "Index out of bounds");
638 unsafe {
639 let ptr = self.ptr.as_ptr().add(index);
640 let reference = &*ptr;
641 reference
642 }
643 }
644}
645
646#[cfg(feature = "serde")]
647impl serde::Serialize for SecureVec<u8> {
648 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
649 where
650 S: serde::Serializer,
651 {
652 let res = self.slice_scope(|slice| serializer.collect_seq(slice.iter()));
653 res
654 }
655}
656
657#[cfg(feature = "serde")]
658impl<'de> serde::Deserialize<'de> for SecureVec<u8> {
659 fn deserialize<D>(deserializer: D) -> Result<SecureVec<u8>, D::Error>
660 where
661 D: serde::Deserializer<'de>,
662 {
663 struct SecureVecVisitor;
664 impl<'de> serde::de::Visitor<'de> for SecureVecVisitor {
665 type Value = SecureVec<u8>;
666 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
667 write!(formatter, "a sequence of bytes")
668 }
669 fn visit_seq<A>(
670 self,
671 mut seq: A,
672 ) -> Result<<Self as serde::de::Visitor<'de>>::Value, A::Error>
673 where
674 A: serde::de::SeqAccess<'de>,
675 {
676 let mut vec = Vec::new();
677 while let Some(byte) = seq.next_element::<u8>()? {
678 vec.push(byte);
679 }
680 SecureVec::from_vec(vec).map_err(serde::de::Error::custom)
681 }
682 }
683 deserializer.deserialize_seq(SecureVecVisitor)
684 }
685}
686
687pub struct Drain<'a, T: Zeroize + 'a> {
695 vec_ref: &'a mut SecureVec<T>,
696 drain_start_index: usize,
697 current_drain_iter_index: usize,
698 drain_end_index: usize,
699
700 original_vec_len: usize, tail_len: usize, _marker: PhantomData<&'a T>,
704}
705
706impl<'a, T: Zeroize> Iterator for Drain<'a, T> {
707 type Item = T;
708
709 fn next(&mut self) -> Option<T> {
710 if self.current_drain_iter_index < self.drain_end_index {
711 unsafe {
713 let item_ptr = self.vec_ref.ptr.as_ptr().add(self.current_drain_iter_index);
714 let item = ptr::read(item_ptr);
715 self.current_drain_iter_index += 1;
716 Some(item)
717 }
718 } else {
719 None
720 }
721 }
722
723 fn size_hint(&self) -> (usize, Option<usize>) {
724 let remaining = self.drain_end_index - self.current_drain_iter_index;
725 (remaining, Some(remaining))
726 }
727}
728
729impl<'a, T: Zeroize> ExactSizeIterator for Drain<'a, T> {}
730
731impl<'a, T: Zeroize> Drop for Drain<'a, T> {
732 fn drop(&mut self) {
733 unsafe {
734 if mem::needs_drop::<T>() {
736 let mut current_ptr =
737 self.vec_ref.ptr.as_ptr().add(self.current_drain_iter_index) as *mut T;
738 let end_ptr = self.vec_ref.ptr.as_ptr().add(self.drain_end_index) as *mut T;
739 while current_ptr < end_ptr {
740 ptr::drop_in_place(current_ptr);
741 current_ptr = current_ptr.add(1);
742 }
743 }
744
745 let hole_dst_ptr = self.vec_ref.ptr.as_ptr().add(self.drain_start_index) as *mut T;
746 let tail_src_ptr = self.vec_ref.ptr.as_ptr().add(self.drain_end_index) as *mut T;
747
748 if self.tail_len > 0 {
749 ptr::copy(tail_src_ptr, hole_dst_ptr, self.tail_len);
750 }
751
752 let new_len = self.drain_start_index + self.tail_len;
754
755 let mut current_cleanup_ptr = self.vec_ref.ptr.as_ptr().add(new_len) as *mut T;
765 let end_cleanup_ptr = self.vec_ref.ptr.as_ptr().add(self.original_vec_len) as *mut T;
766
767 let original_tail_start_ptr_val = tail_src_ptr as usize;
769
770 while current_cleanup_ptr < end_cleanup_ptr {
771 if mem::needs_drop::<T>() {
772 let current_ptr_val = current_cleanup_ptr as usize;
773 let original_tail_end_ptr_val =
774 original_tail_start_ptr_val + self.tail_len * mem::size_of::<T>();
775
776 if current_ptr_val >= original_tail_start_ptr_val
777 && current_ptr_val < original_tail_end_ptr_val
778 {
779 ptr::drop_in_place(current_cleanup_ptr);
782 }
783 }
786
787 (*current_cleanup_ptr).zeroize();
789 current_cleanup_ptr = current_cleanup_ptr.add(1);
790 }
791
792 self.vec_ref.len = new_len;
794
795 self.vec_ref.lock_memory();
797 }
798 }
799}
800
801fn resolve_range_indices<R: RangeBounds<usize>>(range: R, len: usize) -> (usize, usize) {
803 let start_bound = range.start_bound();
804 let end_bound = range.end_bound();
805
806 let start = match start_bound {
807 Bound::Included(&s) => s,
808 Bound::Excluded(&s) => s
809 .checked_add(1)
810 .unwrap_or_else(|| panic!("attempted to start drain at Excluded(usize::MAX)")),
811 Bound::Unbounded => 0,
812 };
813
814 let end = match end_bound {
815 Bound::Included(&e) => e
816 .checked_add(1)
817 .unwrap_or_else(|| panic!("attempted to end drain at Included(usize::MAX)")),
818 Bound::Excluded(&e) => e,
819 Bound::Unbounded => len,
820 };
821
822 if start > end {
823 panic!(
824 "drain range start ({}) must be less than or equal to end ({})",
825 start, end
826 );
827 }
828 if end > len {
829 panic!(
830 "drain range end ({}) out of bounds for slice of length {}",
831 end, len
832 );
833 }
834
835 (start, end)
836}
837
838#[cfg(all(test, feature = "std"))]
839mod tests {
840 use super::*;
841 use std::process::{Command, Stdio};
842 use std::sync::{Arc, Mutex};
843
844 #[test]
845 fn test_from_methods() {
846 let vec: Vec<u8> = vec![1, 2, 3];
847 let secure_vec = SecureVec::from_vec(vec).unwrap();
848
849 secure_vec.slice_scope(|slice| {
850 assert_eq!(slice, &[1, 2, 3]);
851 });
852
853 let mut slice = [3u8, 5];
854 let secure_slice = SecureVec::from_slice_mut(&mut slice).unwrap();
855 assert_eq!(slice, [0, 0]);
856
857 secure_slice.slice_scope(|slice| {
858 assert_eq!(slice, &[3, 5]);
859 });
860
861 let slice = [3u8, 5];
862 let secure_slice = SecureVec::from_slice(&slice).unwrap();
863
864 secure_slice.slice_scope(|slice| {
865 assert_eq!(slice, &[3, 5]);
866 });
867 }
868
869 #[test]
870 fn test_from_secure_array() {
871 let array: SecureArray<u8, 3> = SecureArray::new([1, 2, 3]).unwrap();
872 let vec: SecureVec<u8> = array.into();
873 assert_eq!(vec.len(), 3);
874 vec.slice_scope(|slice| {
875 assert_eq!(slice, &[1, 2, 3]);
876 });
877 }
878
879 #[test]
880 fn lock_unlock() {
881 let secure: SecureVec<u8> = SecureVec::new().unwrap();
882 let size = secure.allocated_byte_size();
883 assert_eq!(size > 0, true);
884
885 let (decrypted, unlocked) = secure.unlock_memory();
886 assert!(decrypted);
887 assert!(unlocked);
888
889 let (encrypted, locked) = secure.lock_memory();
890 assert!(encrypted);
891 assert!(locked);
892
893 let secure: SecureVec<u8> = SecureVec::from_vec(vec![]).unwrap();
894 let size = secure.allocated_byte_size();
895 assert_eq!(size > 0, true);
896
897 let (decrypted, unlocked) = secure.unlock_memory();
898 assert!(decrypted);
899 assert!(unlocked);
900
901 let (encrypted, locked) = secure.lock_memory();
902 assert!(encrypted);
903 assert!(locked);
904
905 let secure: SecureVec<u8> = SecureVec::new_with_capacity(0).unwrap();
906 let size = secure.allocated_byte_size();
907 assert_eq!(size > 0, true);
908
909 let (decrypted, unlocked) = secure.unlock_memory();
910 assert!(decrypted);
911 assert!(unlocked);
912
913 let (encrypted, locked) = secure.lock_memory();
914 assert!(encrypted);
915 assert!(locked);
916 }
917
918 #[test]
919 fn test_thread_safety() {
920 let vec: Vec<u8> = vec![];
921 let secure = SecureVec::from_vec(vec).unwrap();
922 let secure = Arc::new(Mutex::new(secure));
923
924 let mut handles = Vec::new();
925 for i in 0..5u8 {
926 let secure_clone = secure.clone();
927 let handle = std::thread::spawn(move || {
928 let mut secure = secure_clone.lock().unwrap();
929 secure.push(i);
930 });
931 handles.push(handle);
932 }
933
934 for handle in handles {
935 handle.join().unwrap();
936 }
937
938 let sec = secure.lock().unwrap();
939 sec.slice_scope(|slice| {
940 assert_eq!(slice.len(), 5);
941 });
942 }
943
944 #[test]
945 fn test_clone() {
946 let vec: Vec<u8> = vec![1, 2, 3];
947 let secure1 = SecureVec::from_vec(vec).unwrap();
948 let secure2 = secure1.clone();
949
950 secure1.slice_scope(|slice| {
951 secure2.slice_scope(|slice2| {
952 assert_eq!(slice, slice2);
953 });
954 });
955 }
956
957 #[test]
958 fn test_do_not_call_forget_on_drain() {
959 let vec: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
960 let mut secure = SecureVec::from_vec(vec).unwrap();
961 let drain = secure.drain(..3);
962 core::mem::forget(drain);
963 secure.slice_scope(|secure| {
965 assert_eq!(secure.len(), 0);
966 });
967 }
968
969 #[test]
970 fn test_drain() {
971 let vec: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
972 let mut secure = SecureVec::from_vec(vec).unwrap();
973 let mut drain = secure.drain(..3);
974 assert_eq!(drain.next(), Some(1));
975 assert_eq!(drain.next(), Some(2));
976 assert_eq!(drain.next(), Some(3));
977 assert_eq!(drain.next(), None);
978 drop(drain);
979 secure.slice_scope(|secure| {
980 assert_eq!(secure.len(), 7);
981 assert_eq!(secure, &[4, 5, 6, 7, 8, 9, 10]);
982 });
983 }
984
985 #[cfg(feature = "serde")]
986 #[test]
987 fn test_secure_vec_serde() {
988 let vec: Vec<u8> = vec![1, 2, 3];
989 let secure = SecureVec::from_vec(vec).unwrap();
990 let json = serde_json::to_vec(&secure).expect("Serialization failed");
991 let deserialized: SecureVec<u8> =
992 serde_json::from_slice(&json).expect("Deserialization failed");
993 deserialized.slice_scope(|slice| {
994 assert_eq!(slice, &[1, 2, 3]);
995 });
996 }
997
998 #[test]
999 fn test_erase() {
1000 let vec: Vec<u8> = vec![1, 2, 3];
1001 let mut secure = SecureVec::from_vec(vec).unwrap();
1002 secure.erase();
1003 secure.unlock_scope(|secure| {
1004 assert_eq!(secure.len, 0);
1005 assert_eq!(secure.capacity, 3);
1006 });
1007
1008 secure.push(1);
1009 secure.push(2);
1010 secure.push(3);
1011 secure.unlock_scope(|secure| {
1012 assert_eq!(secure[0], 1);
1013 assert_eq!(secure[1], 2);
1014 assert_eq!(secure[2], 3);
1015 assert_eq!(secure.len, 3);
1016 assert_eq!(secure.capacity, 3);
1017 });
1018 }
1019
1020 #[test]
1021 fn test_push() {
1022 let vec: Vec<u8> = Vec::new();
1023 let mut secure = SecureVec::from_vec(vec).unwrap();
1024 for i in 0..30 {
1025 secure.push(i);
1026 }
1027 }
1028
1029 #[test]
1030 fn test_reserve() {
1031 let mut secure: SecureVec<u8> = SecureVec::new().unwrap();
1032 secure.reserve(10);
1033 assert_eq!(secure.capacity, 10);
1034 }
1035
1036 #[test]
1037 fn test_reserve_doubling() {
1038 let mut secure: SecureVec<u8> = SecureVec::new().unwrap();
1039 secure.reserve(10);
1040
1041 for i in 0..9 {
1042 secure.push(i);
1043 }
1044
1045 secure.push(9);
1046 assert_eq!(secure.capacity, 10);
1047 assert_eq!(secure.len(), 10);
1048
1049 secure.push(10);
1050 assert_eq!(secure.capacity, 20);
1051 assert_eq!(secure.len(), 11);
1052 }
1053
1054 #[test]
1055 fn test_index() {
1056 let vec: Vec<u8> = vec![1, 2, 3];
1057 let secure = SecureVec::from_vec(vec).unwrap();
1058 secure.unlock_scope(|secure| {
1059 assert_eq!(secure[0], 1);
1060 assert_eq!(secure[1], 2);
1061 assert_eq!(secure[2], 3);
1062 });
1063 }
1064
1065 #[test]
1066 fn test_slice_scoped() {
1067 let vec: Vec<u8> = vec![1, 2, 3];
1068 let secure = SecureVec::from_vec(vec).unwrap();
1069 secure.slice_scope(|slice| {
1070 assert_eq!(slice, &[1, 2, 3]);
1071 });
1072 }
1073
1074 #[test]
1075 fn test_slice_mut_scoped() {
1076 let vec: Vec<u8> = vec![1, 2, 3];
1077 let mut secure = SecureVec::from_vec(vec).unwrap();
1078
1079 secure.slice_mut_scope(|slice| {
1080 slice[0] = 4;
1081 assert_eq!(slice, &mut [4, 2, 3]);
1082 });
1083
1084 secure.slice_scope(|slice| {
1085 assert_eq!(slice, &[4, 2, 3]);
1086 });
1087 }
1088
1089 #[test]
1090 fn test_iter_scoped() {
1091 let vec: Vec<u8> = vec![1, 2, 3];
1092 let secure = SecureVec::from_vec(vec).unwrap();
1093 let sum: u8 = secure.iter_scope(|iter| iter.map(|&x| x).sum());
1094
1095 assert_eq!(sum, 6);
1096
1097 let secure: SecureVec<u8> = SecureVec::new_with_capacity(3).unwrap();
1098 let sum: u8 = secure.iter_scope(|iter| iter.map(|&x| x).sum());
1099
1100 assert_eq!(sum, 0);
1101 }
1102
1103 #[test]
1104 fn test_iter_mut_scoped() {
1105 let vec: Vec<u8> = vec![1, 2, 3];
1106 let mut secure = SecureVec::from_vec(vec).unwrap();
1107 secure.iter_mut_scope(|iter| {
1108 for elem in iter {
1109 *elem += 1;
1110 }
1111 });
1112
1113 secure.slice_scope(|slice| {
1114 assert_eq!(slice, &[2, 3, 4]);
1115 });
1116 }
1117
1118 #[test]
1119 fn test_index_should_fail_when_locked() {
1120 let arg = "CRASH_TEST_SECUREVEC_LOCKED";
1121
1122 if std::env::args().any(|a| a == arg) {
1123 let vec: Vec<u8> = vec![1, 2, 3];
1124 let secure = SecureVec::from_vec(vec).unwrap();
1125 let _value = core::hint::black_box(secure[0]);
1126
1127 std::process::exit(1);
1128 }
1129
1130 let child = Command::new(std::env::current_exe().unwrap())
1131 .arg("vec::tests::test_index_should_fail_when_locked")
1132 .arg(arg)
1133 .arg("--nocapture")
1134 .stdout(Stdio::piped())
1135 .stderr(Stdio::piped())
1136 .spawn()
1137 .expect("Failed to spawn child process");
1138
1139 let output = child.wait_with_output().expect("Failed to wait on child");
1140 let status = output.status;
1141
1142 assert!(
1143 !status.success(),
1144 "Process exited successfully with code {:?}, but it should have crashed.",
1145 status.code()
1146 );
1147
1148 #[cfg(unix)]
1149 {
1150 use std::os::unix::process::ExitStatusExt;
1151 let signal = status
1152 .signal()
1153 .expect("Process was not terminated by a signal on Unix.");
1154 assert!(
1155 signal == libc::SIGSEGV || signal == libc::SIGBUS,
1156 "Process terminated with unexpected signal: {}",
1157 signal
1158 );
1159 println!(
1160 "Test passed: Process correctly terminated with signal {}.",
1161 signal
1162 );
1163 }
1164
1165 #[cfg(windows)]
1166 {
1167 const STATUS_ACCESS_VIOLATION: i32 = 0xC0000005_u32 as i32;
1168 assert_eq!(
1169 status.code(),
1170 Some(STATUS_ACCESS_VIOLATION),
1171 "Process exited with unexpected code: {:x?}. Expected STATUS_ACCESS_VIOLATION.",
1172 status.code()
1173 );
1174 eprintln!("Test passed: Process correctly terminated with STATUS_ACCESS_VIOLATION.");
1175 }
1176 }
1177}