Задокументированные предусловия безопасности
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// ...
///
/// # Safety
///
/// Эта функция легко может вызвать неопределённое поведение. Убедитесь, что:
///
/// - указатель `source` не равен null и не висящий
/// - данные `source` заканчиваются нулевым байтом внутри своего выделения памяти
/// - данные `source` не освобождены (инварианты времени жизни сохраняются)
/// - данные `source` содержат меньше `isize::MAX` байт
pub unsafe fn copy(dest: &mut [u8], source: *const u8) {
let source = {
let mut len = 0;
let mut end = source;
// SAFETY: вызывающий код передал ненулевой указатель
while unsafe { *end != 0 } {
len += 1;
// SAFETY: вызывающий код передал данные длиной < isize:MAX
end = unsafe { end.add(1) };
}
// SAFETY: вызывающий код соблюдает требования к времени жизни и псевдонимам
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));
}
Изменения по сравнению с предыдущими итерациями:
copyпомечена как unsafe- Предусловия безопасности задокументированы
- встроенные комментарии о безопасности
Небезопасная функция корректна, когда задокументированы и её предусловия безопасности, и её внутренние небезопасные блоки.
Нужны исправления в main.
aне удовлетворяет одному из предусловийcopy(данныеsourceдолжны заканчиваться нулевым байтом внутри своего выделения памяти)- Нужен комментарий SAFETY