Documented safety preconditions
/// ... /// /// # Safety /// /// This function can easily trigger undefined behavior. Ensure that: /// /// - `source` pointer is non-null and non-dangling /// - `source` data ends with a null byte within its memory allocation /// - `source` data is not freed (its lifetime invariants are preserved) /// - `source` data contains fewer than `isize::MAX` bytes pub unsafe fn copy(dest: &mut [u8], source: *const u8) { let source = { let mut len = 0; let mut end = source; // SAFETY: Caller has provided a non-null pointer while unsafe { *end != 0 } { len += 1; // SAFETY: Caller has provided a data with length < isize:MAX end = unsafe { end.add(1) }; } // SAFETY: Caller maintains lifetime and aliasing requirements unsafe { std::slice::from_raw_parts(source, len + 1) } }; for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = [114, 117, 115, 116].as_ptr(); let b = &mut [82, 85, 83, 84, 0]; println!("{}", String::from_utf8_lossy(b)); unsafe { copy(b, a); } println!("{}", String::from_utf8_lossy(b)); }
Changes to previous iterations:
copymarked as unsafe- Safety preconditions are documented
- inline safety comments
An unsafe function is sound when both its safety preconditions and its internal unsafe blocks are documented.
Fixes needed in main.
adoes not satisfy one of the preconditions ofcopy(source` data ends with a null byte within its memory allocation)- SAFETY comment needed