Skip to content

Commit 97d1f8d

Browse files
committed
Add missing _zeroed varants to AllocRef
1 parent 4d1241f commit 97d1f8d

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed

src/libcore/alloc.rs

+137
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,59 @@ pub unsafe trait AllocRef {
853853
result
854854
}
855855

856+
/// Behaves like `realloc`, but also ensures that the new contents
857+
/// are set to zero before being returned.
858+
///
859+
/// # Safety
860+
///
861+
/// This function is unsafe for the same reasons that `realloc` is.
862+
///
863+
/// # Errors
864+
///
865+
/// Returns `Err` only if the new layout
866+
/// does not meet the allocator's size
867+
/// and alignment constraints of the allocator, or if reallocation
868+
/// otherwise fails.
869+
///
870+
/// Implementations are encouraged to return `Err` on memory
871+
/// exhaustion rather than panicking or aborting, but this is not
872+
/// a strict requirement. (Specifically: it is *legal* to
873+
/// implement this trait atop an underlying native allocation
874+
/// library that aborts on memory exhaustion.)
875+
///
876+
/// Clients wishing to abort computation in response to a
877+
/// reallocation error are encouraged to call the [`handle_alloc_error`] function,
878+
/// rather than directly invoking `panic!` or similar.
879+
///
880+
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
881+
unsafe fn realloc_zeroed(
882+
&mut self,
883+
ptr: NonNull<u8>,
884+
layout: Layout,
885+
new_size: usize,
886+
) -> Result<NonNull<u8>, AllocErr> {
887+
let old_size = layout.size();
888+
889+
if new_size >= old_size {
890+
if let Ok(()) = self.grow_in_place_zeroed(ptr, layout, new_size) {
891+
return Ok(ptr);
892+
}
893+
} else if new_size < old_size {
894+
if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) {
895+
return Ok(ptr);
896+
}
897+
}
898+
899+
// otherwise, fall back on alloc + copy + dealloc.
900+
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
901+
let result = self.alloc_zeroed(new_layout);
902+
if let Ok(new_ptr) = result {
903+
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
904+
self.dealloc(ptr, layout);
905+
}
906+
result
907+
}
908+
856909
/// Behaves like `alloc`, but also ensures that the contents
857910
/// are set to zero before being returned.
858911
///
@@ -904,6 +957,31 @@ pub unsafe trait AllocRef {
904957
self.alloc(layout).map(|p| Excess(p, usable_size.1))
905958
}
906959

960+
/// Behaves like `alloc`, but also returns the whole size of
961+
/// the returned block. For some `layout` inputs, like arrays, this
962+
/// may include extra storage usable for additional data.
963+
/// Also it ensures that the contents are set to zero before being returned.
964+
///
965+
/// # Safety
966+
///
967+
/// This function is unsafe for the same reasons that `alloc` is.
968+
///
969+
/// # Errors
970+
///
971+
/// Returning `Err` indicates that either memory is exhausted or
972+
/// `layout` does not meet allocator's size or alignment
973+
/// constraints, just as in `alloc`.
974+
///
975+
/// Clients wishing to abort computation in response to an
976+
/// allocation error are encouraged to call the [`handle_alloc_error`] function,
977+
/// rather than directly invoking `panic!` or similar.
978+
///
979+
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
980+
unsafe fn alloc_excess_zeroed(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
981+
let usable_size = self.usable_size(&layout);
982+
self.alloc_zeroed(layout).map(|p| Excess(p, usable_size.1))
983+
}
984+
907985
/// Behaves like `realloc`, but also returns the whole size of
908986
/// the returned block. For some `layout` inputs, like arrays, this
909987
/// may include extra storage usable for additional data.
@@ -934,6 +1012,37 @@ pub unsafe trait AllocRef {
9341012
self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1))
9351013
}
9361014

1015+
/// Behaves like `realloc`, but also returns the whole size of
1016+
/// the returned block. For some `layout` inputs, like arrays, this
1017+
/// may include extra storage usable for additional data.
1018+
/// Also it ensures that the contents are set to zero before being returned.
1019+
///
1020+
/// # Safety
1021+
///
1022+
/// This function is unsafe for the same reasons that `realloc` is.
1023+
///
1024+
/// # Errors
1025+
///
1026+
/// Returning `Err` indicates that either memory is exhausted or
1027+
/// `layout` does not meet allocator's size or alignment
1028+
/// constraints, just as in `realloc`.
1029+
///
1030+
/// Clients wishing to abort computation in response to a
1031+
/// reallocation error are encouraged to call the [`handle_alloc_error`] function,
1032+
/// rather than directly invoking `panic!` or similar.
1033+
///
1034+
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
1035+
unsafe fn realloc_excess_zeroed(
1036+
&mut self,
1037+
ptr: NonNull<u8>,
1038+
layout: Layout,
1039+
new_size: usize,
1040+
) -> Result<Excess, AllocErr> {
1041+
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
1042+
let usable_size = self.usable_size(&new_layout);
1043+
self.realloc_zeroed(ptr, layout, new_size).map(|p| Excess(p, usable_size.1))
1044+
}
1045+
9371046
/// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
9381047
///
9391048
/// If this returns `Ok`, then the allocator has asserted that the
@@ -983,6 +1092,34 @@ pub unsafe trait AllocRef {
9831092
if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) }
9841093
}
9851094

1095+
/// Behaves like `grow_in_place`, but also ensures that the new
1096+
/// contents are set to zero before being returned.
1097+
///
1098+
/// # Safety
1099+
///
1100+
/// This function is unsafe for the same reasons that `grow_in_place` is.
1101+
///
1102+
/// # Errors
1103+
///
1104+
/// Returns `Err(CannotReallocInPlace)` when the allocator is
1105+
/// unable to assert that the memory block referenced by `ptr`
1106+
/// could fit `layout`.
1107+
///
1108+
/// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
1109+
/// function; clients are expected either to be able to recover from
1110+
/// `grow_in_place` failures without aborting, or to fall back on
1111+
/// another reallocation method before resorting to an abort.
1112+
unsafe fn grow_in_place_zeroed(
1113+
&mut self,
1114+
ptr: NonNull<u8>,
1115+
layout: Layout,
1116+
new_size: usize,
1117+
) -> Result<(), CannotReallocInPlace> {
1118+
self.grow_in_place(ptr, layout, new_size)?;
1119+
ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size());
1120+
Ok(())
1121+
}
1122+
9861123
/// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
9871124
///
9881125
/// If this returns `Ok`, then the allocator has asserted that the

0 commit comments

Comments
 (0)